diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9a0e72d7b640a..8b425ce0267d2 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1118,6 +1118,10 @@ where fn is_unit(this: TyAndLayout<'tcx>) -> bool { matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0) } + + fn is_transparent(this: TyAndLayout<'tcx>) -> bool { + matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().transparent()) + } } /// Calculates whether a function's ABI can unwind or not. diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index d90dce2a08785..93a2045632a84 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -89,6 +89,17 @@ where } FieldsShape::Union(_) => { if !arg_layout.is_zst() { + if arg_layout.is_transparent() { + let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1; + return should_use_fp_conv_helper( + cx, + &non_1zst_elem, + xlen, + flen, + field1_kind, + field2_kind, + ); + } return Err(CannotUseFpConv); } } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 636adcf6b178d..74fe98920c459 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -66,6 +66,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug { fn is_never(this: TyAndLayout<'a, Self>) -> bool; fn is_tuple(this: TyAndLayout<'a, Self>) -> bool; fn is_unit(this: TyAndLayout<'a, Self>) -> bool; + fn is_transparent(this: TyAndLayout<'a, Self>) -> bool; } impl<'a, Ty> TyAndLayout<'a, Ty> { @@ -136,6 +137,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty::is_unit(self) } + pub fn is_transparent(self) -> bool + where + Ty: TyAbiInterface<'a, C>, + { + Ty::is_transparent(self) + } + pub fn offset_of_subfield(self, cx: &C, indices: impl Iterator) -> Size where Ty: TyAbiInterface<'a, C>, diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 0dbac56b47dd4..01bb1ca70eb4c 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -3,10 +3,13 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::{ normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution, }; -use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext}; +use rustc_trait_selection::traits::{ + self, FulfillmentErrorCode, ObligationCause, SelectionContext, +}; use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { @@ -40,6 +43,27 @@ fn normalize_projection_ty<'tcx>( &mut obligations, ); ocx.register_obligations(obligations); + // #112047: With projections and opaques, we are able to create opaques that + // are recursive (given some substitution of the opaque's type variables). + // In that case, we may only realize a cycle error when calling + // `normalize_erasing_regions` in mono. + if !ocx.infcx.next_trait_solver() { + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + // Rustdoc may attempt to normalize type alias types which are not + // well-formed. Rustdoc also normalizes types that are just not + // well-formed, since we don't do as much HIR analysis (checking + // that impl vars are constrained by the signature, for example). + if !tcx.sess.opts.actually_rustdoc { + for error in &errors { + if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code { + ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle); + } + } + } + return Err(NoSolution); + } + } // FIXME(associated_const_equality): All users of normalize_projection_ty expected // a type, but there is the possibility it could've been a const now. Maybe change // it to a Term later? diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 3144db197074b..290f649f9acd6 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -957,6 +957,7 @@ impl f32 { } else if self == other { if self.is_sign_negative() && other.is_sign_positive() { self } else { other } } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. self + other } } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 20833defc41b8..7569d2cd6ca97 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -968,6 +968,7 @@ impl f64 { } else if self == other { if self.is_sign_negative() && other.is_sign_positive() { self } else { other } } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. self + other } } diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index 4fb00f65dc19d..b0a97b540ec75 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -134,7 +134,7 @@ pub unsafe fn setup(build: &mut Build) { // If this failed, well at least we tried! An example of DuplicateHandle // failing in the past has been when the wrong python2 package spawned this // build system (e.g., the `python2` package in MSYS instead of - // `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure + // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure // mode" here is that we only clean everything up when the build system // dies, not when the python parent does, so not too bad. if r.is_err() { diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index f4d759673700d..9a59d80556e0f 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -32,6 +32,19 @@ This should not be interpreted as forbidding developers from following a non-default style, or forbidding tools from adding any particular configuration options. +## Bugs + +If the style guide differs from rustfmt, that may represent a bug in rustfmt, +or a bug in the style guide; either way, please report it to the style team or +the rustfmt team or both, for investigation and fix. + +If implementing a new formatting tool based on the style guide and default Rust +style, please test it on the corpus of existing Rust code, and avoid causing +widespread breakage. The implementation and testing of such a tool may surface +bugs in either the style guide or rustfmt, as well as bugs in the tool itself. + +We typically resolve bugs in a fashion that avoids widespread breakage. + ## Formatting conventions ### Indentation and line width diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 59958fbaef918..6dbf2185e3d03 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -868,7 +868,7 @@ impl<'tcx> ExtraInfo<'tcx> { #[derive(Eq, PartialEq, Clone, Debug)] pub(crate) struct LangString { - original: String, + pub(crate) original: String, pub(crate) should_panic: bool, pub(crate) no_run: bool, pub(crate) ignore: Ignore, @@ -893,11 +893,13 @@ pub(crate) enum Ignore { /// ```eBNF /// lang-string = *(token-list / delimited-attribute-list / comment) /// -/// bareword = CHAR *(CHAR) +/// bareword = LEADINGCHAR *(CHAR) +/// bareword-without-leading-char = CHAR *(CHAR) /// quoted-string = QUOTE *(NONQUOTE) QUOTE /// token = bareword / quoted-string +/// token-without-leading-char = bareword-without-leading-char / quoted-string /// sep = COMMA/WS *(COMMA/WS) -/// attribute = (DOT token)/(token EQUAL token) +/// attribute = (DOT token)/(token EQUAL token-without-leading-char) /// attribute-list = [sep] attribute *(sep attribute) [sep] /// delimited-attribute-list = OPEN-CURLY-BRACKET attribute-list CLOSE-CURLY-BRACKET /// token-list = [sep] token *(sep token) [sep] @@ -907,8 +909,15 @@ pub(crate) enum Ignore { /// CLOSE_PARENT = ")" /// OPEN-CURLY-BRACKET = "{" /// CLOSE-CURLY-BRACKET = "}" -/// CHAR = ALPHA / DIGIT / "_" / "-" / ":" -/// QUOTE = %x22 +/// LEADINGCHAR = ALPHA | DIGIT | "_" | "-" | ":" +/// ; All ASCII punctuation except comma, quote, equals, backslash, grave (backquote) and braces. +/// ; Comma is used to separate language tokens, so it can't be used in one. +/// ; Quote is used to allow otherwise-disallowed characters in language tokens. +/// ; Equals is used to make key=value pairs in attribute blocks. +/// ; Backslash and grave are special Markdown characters. +/// ; Braces are used to start an attribute block. +/// CHAR = ALPHA | DIGIT | "_" | "-" | ":" | "." | "!" | "#" | "$" | "%" | "&" | "*" | "+" | "/" | +/// ";" | "<" | ">" | "?" | "@" | "^" | "|" | "~" /// NONQUOTE = %x09 / %x20 / %x21 / %x23-7E ; TAB / SPACE / all printable characters except `"` /// COMMA = "," /// DOT = "." @@ -932,9 +941,12 @@ pub(crate) enum LangStringToken<'a> { KeyValueAttribute(&'a str, &'a str), } -fn is_bareword_char(c: char) -> bool { +fn is_leading_char(c: char) -> bool { c == '_' || c == '-' || c == ':' || c.is_ascii_alphabetic() || c.is_ascii_digit() } +fn is_bareword_char(c: char) -> bool { + is_leading_char(c) || ".!#$%&*+/;<>?@^|~".contains(c) +} fn is_separator(c: char) -> bool { c == ' ' || c == ',' || c == '\t' } @@ -1077,7 +1089,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return self.next(); } else if c == '.' { return self.parse_class(pos); - } else if c == '"' || is_bareword_char(c) { + } else if c == '"' || is_leading_char(c) { return self.parse_key_value(c, pos); } else { self.emit_error(format!("unexpected character `{c}`")); @@ -1107,7 +1119,11 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return None; } let indices = self.parse_string(pos)?; - if let Some((_, c)) = self.inner.peek().copied() && c != '{' && !is_separator(c) && c != '(' { + if let Some((_, c)) = self.inner.peek().copied() && + c != '{' && + !is_separator(c) && + c != '(' + { self.emit_error(format!("expected ` `, `{{` or `,` after `\"`, found `{c}`")); return None; } @@ -1115,8 +1131,6 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } else if c == '{' { self.is_in_attribute_block = true; return self.next(); - } else if is_bareword_char(c) { - continue; } else if is_separator(c) { if pos != start { return Some(LangStringToken::LangToken(&self.data[start..pos])); @@ -1130,6 +1144,10 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return Some(LangStringToken::LangToken(&self.data[start..pos])); } return self.next(); + } else if pos == start && is_leading_char(c) { + continue; + } else if pos != start && is_bareword_char(c) { + continue; } else { self.emit_error(format!("unexpected character `{c}`")); return None; @@ -1158,6 +1176,29 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { } } +fn tokens(string: &str) -> impl Iterator> { + // Pandoc, which Rust once used for generating documentation, + // expects lang strings to be surrounded by `{}` and for each token + // to be proceeded by a `.`. Since some of these lang strings are still + // loose in the wild, we strip a pair of surrounding `{}` from the lang + // string and a leading `.` from each token. + + let string = string.trim(); + + let first = string.chars().next(); + let last = string.chars().last(); + + let string = + if first == Some('{') && last == Some('}') { &string[1..string.len() - 1] } else { string }; + + string + .split(|c| c == ',' || c == ' ' || c == '\t') + .map(str::trim) + .map(|token| token.strip_prefix('.').unwrap_or(token)) + .filter(|token| !token.is_empty()) + .map(|token| LangStringToken::LangToken(token)) +} + impl Default for LangString { fn default() -> Self { Self { @@ -1208,122 +1249,130 @@ impl LangString { data.original = string.to_owned(); - for token in TagIterator::new(string, extra) { - match token { - LangStringToken::LangToken("should_panic") => { - data.should_panic = true; - seen_rust_tags = !seen_other_tags; - } - LangStringToken::LangToken("no_run") => { - data.no_run = true; - seen_rust_tags = !seen_other_tags; - } - LangStringToken::LangToken("ignore") => { - data.ignore = Ignore::All; - seen_rust_tags = !seen_other_tags; - } - LangStringToken::LangToken(x) if x.starts_with("ignore-") => { - if enable_per_target_ignores { - ignores.push(x.trim_start_matches("ignore-").to_owned()); + let mut call = |tokens: &mut dyn Iterator>| { + for token in tokens { + match token { + LangStringToken::LangToken("should_panic") => { + data.should_panic = true; seen_rust_tags = !seen_other_tags; } - } - LangStringToken::LangToken("rust") => { - data.rust = true; - seen_rust_tags = true; - } - LangStringToken::LangToken("custom") => { - if custom_code_classes_in_docs { - seen_custom_tag = true; - } else { - seen_other_tags = true; + LangStringToken::LangToken("no_run") => { + data.no_run = true; + seen_rust_tags = !seen_other_tags; } - } - LangStringToken::LangToken("test_harness") => { - data.test_harness = true; - seen_rust_tags = !seen_other_tags || seen_rust_tags; - } - LangStringToken::LangToken("compile_fail") => { - data.compile_fail = true; - seen_rust_tags = !seen_other_tags || seen_rust_tags; - data.no_run = true; - } - LangStringToken::LangToken(x) if x.starts_with("edition") => { - data.edition = x[7..].parse::().ok(); - } - LangStringToken::LangToken(x) - if allow_error_code_check && x.starts_with('E') && x.len() == 5 => - { - if x[1..].parse::().is_ok() { - data.error_codes.push(x.to_owned()); + LangStringToken::LangToken("ignore") => { + data.ignore = Ignore::All; + seen_rust_tags = !seen_other_tags; + } + LangStringToken::LangToken(x) if x.starts_with("ignore-") => { + if enable_per_target_ignores { + ignores.push(x.trim_start_matches("ignore-").to_owned()); + seen_rust_tags = !seen_other_tags; + } + } + LangStringToken::LangToken("rust") => { + data.rust = true; + seen_rust_tags = true; + } + LangStringToken::LangToken("custom") => { + if custom_code_classes_in_docs { + seen_custom_tag = true; + } else { + seen_other_tags = true; + } + } + LangStringToken::LangToken("test_harness") => { + data.test_harness = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; - } else { - seen_other_tags = true; } - } - LangStringToken::LangToken(x) if extra.is_some() => { - let s = x.to_lowercase(); - if let Some((flag, help)) = if s == "compile-fail" - || s == "compile_fail" - || s == "compilefail" + LangStringToken::LangToken("compile_fail") => { + data.compile_fail = true; + seen_rust_tags = !seen_other_tags || seen_rust_tags; + data.no_run = true; + } + LangStringToken::LangToken(x) if x.starts_with("edition") => { + data.edition = x[7..].parse::().ok(); + } + LangStringToken::LangToken(x) + if allow_error_code_check && x.starts_with('E') && x.len() == 5 => { - Some(( - "compile_fail", - "the code block will either not be tested if not marked as a rust one \ - or won't fail if it compiles successfully", - )) - } else if s == "should-panic" || s == "should_panic" || s == "shouldpanic" { - Some(( - "should_panic", - "the code block will either not be tested if not marked as a rust one \ - or won't fail if it doesn't panic when running", - )) - } else if s == "no-run" || s == "no_run" || s == "norun" { - Some(( - "no_run", - "the code block will either not be tested if not marked as a rust one \ - or will be run (which you might not want)", - )) - } else if s == "test-harness" || s == "test_harness" || s == "testharness" { - Some(( - "test_harness", - "the code block will either not be tested if not marked as a rust one \ - or the code will be wrapped inside a main function", - )) - } else { - None - } { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr_with_help( - format!("unknown attribute `{x}`. Did you mean `{flag}`?"), - help, - ); + if x[1..].parse::().is_ok() { + data.error_codes.push(x.to_owned()); + seen_rust_tags = !seen_other_tags || seen_rust_tags; + } else { + seen_other_tags = true; } } - seen_other_tags = true; - data.unknown.push(x.to_owned()); - } - LangStringToken::LangToken(x) => { - seen_other_tags = true; - data.unknown.push(x.to_owned()); - } - LangStringToken::KeyValueAttribute(key, value) => { - if custom_code_classes_in_docs { - if key == "class" { - data.added_classes.push(value.to_owned()); - } else if let Some(extra) = extra { - extra.error_invalid_codeblock_attr(format!( - "unsupported attribute `{key}`" - )); + LangStringToken::LangToken(x) if extra.is_some() => { + let s = x.to_lowercase(); + if let Some((flag, help)) = if s == "compile-fail" + || s == "compile_fail" + || s == "compilefail" + { + Some(( + "compile_fail", + "the code block will either not be tested if not marked as a rust one \ + or won't fail if it compiles successfully", + )) + } else if s == "should-panic" || s == "should_panic" || s == "shouldpanic" { + Some(( + "should_panic", + "the code block will either not be tested if not marked as a rust one \ + or won't fail if it doesn't panic when running", + )) + } else if s == "no-run" || s == "no_run" || s == "norun" { + Some(( + "no_run", + "the code block will either not be tested if not marked as a rust one \ + or will be run (which you might not want)", + )) + } else if s == "test-harness" || s == "test_harness" || s == "testharness" { + Some(( + "test_harness", + "the code block will either not be tested if not marked as a rust one \ + or the code will be wrapped inside a main function", + )) + } else { + None + } { + if let Some(extra) = extra { + extra.error_invalid_codeblock_attr_with_help( + format!("unknown attribute `{x}`. Did you mean `{flag}`?"), + help, + ); + } } - } else { seen_other_tags = true; + data.unknown.push(x.to_owned()); + } + LangStringToken::LangToken(x) => { + seen_other_tags = true; + data.unknown.push(x.to_owned()); + } + LangStringToken::KeyValueAttribute(key, value) => { + if custom_code_classes_in_docs { + if key == "class" { + data.added_classes.push(value.to_owned()); + } else if let Some(extra) = extra { + extra.error_invalid_codeblock_attr(format!( + "unsupported attribute `{key}`" + )); + } + } else { + seen_other_tags = true; + } + } + LangStringToken::ClassAttribute(class) => { + data.added_classes.push(class.to_owned()); } - } - LangStringToken::ClassAttribute(class) => { - data.added_classes.push(class.to_owned()); } } + }; + + if custom_code_classes_in_docs { + call(&mut TagIterator::new(string, extra).into_iter()) + } else { + call(&mut tokens(string)) } // ignore-foo overrides ignore diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 32957ac57fae9..5eba1d0609f38 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -226,13 +226,28 @@ fn test_lang_string_parse() { ..Default::default() }); // error - t(LangString { original: "{.first.second}".into(), rust: true, ..Default::default() }); + t(LangString { + original: "{.first.second}".into(), + rust: true, + added_classes: vec!["first.second".into()], + ..Default::default() + }); // error t(LangString { original: "{class=first=second}".into(), rust: true, ..Default::default() }); // error - t(LangString { original: "{class=first.second}".into(), rust: true, ..Default::default() }); + t(LangString { + original: "{class=first.second}".into(), + rust: true, + added_classes: vec!["first.second".into()], + ..Default::default() + }); // error - t(LangString { original: "{class=.first}".into(), rust: true, ..Default::default() }); + t(LangString { + original: "{class=.first}".into(), + added_classes: vec![".first".into()], + rust: true, + ..Default::default() + }); t(LangString { original: r#"{class="first"}"#.into(), added_classes: vec!["first".into()], diff --git a/src/librustdoc/passes/check_custom_code_classes.rs b/src/librustdoc/passes/check_custom_code_classes.rs index 1a703a4e96755..6266d3ff51d64 100644 --- a/src/librustdoc/passes/check_custom_code_classes.rs +++ b/src/librustdoc/passes/check_custom_code_classes.rs @@ -21,6 +21,10 @@ pub(crate) const CHECK_CUSTOM_CODE_CLASSES: Pass = Pass { }; pub(crate) fn check_custom_code_classes(krate: Crate, cx: &mut DocContext<'_>) -> Crate { + if cx.tcx.features().custom_code_classes_in_docs { + // Nothing to check here if the feature is enabled. + return krate; + } let mut coll = CustomCodeClassLinter { cx }; coll.fold_crate(krate) @@ -59,7 +63,7 @@ pub(crate) fn look_for_custom_classes<'tcx>(cx: &DocContext<'tcx>, item: &Item) let dox = item.attrs.doc_value(); find_codes(&dox, &mut tests, ErrorCodes::No, false, None, true, true); - if !tests.custom_classes_found.is_empty() && !cx.tcx.features().custom_code_classes_in_docs { + if !tests.custom_classes_found.is_empty() { let span = item.attr_span(cx.tcx); let sess = &cx.tcx.sess.parse_sess; let mut err = sess diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs index dd8759b7e378a..5398d5833c75e 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs @@ -57,25 +57,23 @@ pub fn foo8() {} /// ```{class=one=two} /// main; /// ``` -//~^^^ ERROR unexpected `=` +//~^^^ ERROR unexpected `=` character pub fn foo9() {} /// ```{.one.two} /// main; /// ``` -//~^^^ ERROR unexpected `.` character pub fn foo10() {} -/// ```{class=.one} +/// ```{class=(one} /// main; /// ``` -//~^^^ ERROR unexpected `.` character after `=` +//~^^^ ERROR unexpected `(` character after `=` pub fn foo11() {} /// ```{class=one.two} /// main; /// ``` -//~^^^ ERROR unexpected `.` character pub fn foo12() {} /// ```{(comment)} diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr index 3e0dc4b2f7a6b..14b4b3bab3fad 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr @@ -77,37 +77,21 @@ LL | | /// main; LL | | /// ``` | |_______^ -error: unexpected `.` character - --> $DIR/custom_code_classes_in_docs-warning.rs:63:1 +error: unexpected `(` character after `=` + --> $DIR/custom_code_classes_in_docs-warning.rs:68:1 | -LL | / /// ```{.one.two} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected `.` character after `=` - --> $DIR/custom_code_classes_in_docs-warning.rs:69:1 - | -LL | / /// ```{class=.one} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected `.` character - --> $DIR/custom_code_classes_in_docs-warning.rs:75:1 - | -LL | / /// ```{class=one.two} +LL | / /// ```{class=(one} LL | | /// main; LL | | /// ``` | |_______^ error: unexpected character `(` - --> $DIR/custom_code_classes_in_docs-warning.rs:81:1 + --> $DIR/custom_code_classes_in_docs-warning.rs:79:1 | LL | / /// ```{(comment)} LL | | /// main; LL | | /// ``` | |_______^ -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors diff --git a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs b/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs index 3f0f8b5b9f997..99263a944f810 100644 --- a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs +++ b/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs @@ -8,3 +8,8 @@ //~| NOTE see issue #79483 //~| HELP add `#![feature(custom_code_classes_in_docs)]` to the crate attributes to enable pub struct Bar; + +/// ```ASN.1 +/// int main(void) { return 0; } +/// ``` +pub struct Bar2; diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index b3e75bb8233e3..d4f42cdda97a7 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -10,7 +10,6 @@ use std::ptr::NonNull; // Hence there are `cfg` throughout this test to disable parts of it on those targets. // sparc64: https://github.com/rust-lang/rust/issues/115336 // mips64: https://github.com/rust-lang/rust/issues/115404 -// riscv64: https://github.com/rust-lang/rust/issues/115481 // loongarch64: https://github.com/rust-lang/rust/issues/115509 macro_rules! assert_abi_compatible { @@ -110,7 +109,7 @@ macro_rules! test_transparent { test_abi_compatible!(wrap1, $t, Wrapper1<$t>); test_abi_compatible!(wrap2, $t, Wrapper2<$t>); test_abi_compatible!(wrap3, $t, Wrapper3<$t>); - #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] + #[cfg(not(target_arch = "loongarch64"))] test_abi_compatible!(wrap4, $t, WrapperUnion<$t>); } }; diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs new file mode 100644 index 0000000000000..85d17ddff94d8 --- /dev/null +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs @@ -0,0 +1,38 @@ +// edition: 2021 +// build-fail +//~^^ ERROR overflow evaluating the requirement `::{opaque#0} == _` + +#![feature(async_fn_in_trait)] + +fn main() { + let _ = async { + A.first().await.second().await; + }; +} + +pub trait First { + type Second: Second; + async fn first(self) -> Self::Second; +} + +struct A; + +impl First for A { + type Second = A; + async fn first(self) -> Self::Second { + A + } +} + +pub trait Second { + async fn second(self); +} + +impl Second for C +where + C: First, +{ + async fn second(self) { + self.first().await.second().await; + } +} diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr new file mode 100644 index 0000000000000..3f487a6e5fe58 --- /dev/null +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr @@ -0,0 +1,5 @@ +error[E0275]: overflow evaluating the requirement `::{opaque#0} == _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs new file mode 100644 index 0000000000000..baa22e1ce1806 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs @@ -0,0 +1,29 @@ +// edition: 2021 +// build-fail +//~^^ ERROR overflow evaluating the requirement `<() as Recur>::Recur == _` + +#![feature(impl_trait_in_assoc_type)] + +use core::future::Future; + +trait Recur { + type Recur: Future; + + fn recur(self) -> Self::Recur; +} + +async fn recur(t: impl Recur) { + t.recur().await; +} + +impl Recur for () { + type Recur = impl Future; + + fn recur(self) -> Self::Recur { + async move { recur(self).await; } + } +} + +fn main() { + recur(()); +} diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr new file mode 100644 index 0000000000000..0238694c24d3c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr @@ -0,0 +1,5 @@ +error[E0275]: overflow evaluating the requirement `<() as Recur>::Recur == _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs new file mode 100644 index 0000000000000..1ccd1b0cbad4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs @@ -0,0 +1,40 @@ +// edition: 2021 +// build-fail +//~^^ ERROR overflow evaluating the requirement `<() as B>::Assoc == _` + +#![feature(rustc_attrs)] +#![feature(impl_trait_in_assoc_type)] + +#[rustc_coinductive] +trait A { + type Assoc; + + fn test() -> Self::Assoc; +} + +#[rustc_coinductive] +trait B { + type Assoc; + + fn test() -> Self::Assoc; +} + +impl B for T { + type Assoc = impl Sized; + + fn test() -> ::Assoc { + ::test() + } +} + +fn main() { + <() as A>::test(); +} + +impl A for T { + type Assoc = impl Sized; + + fn test() -> ::Assoc { + ::test() + } +} diff --git a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr new file mode 100644 index 0000000000000..49c59f7eb37a1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr @@ -0,0 +1,5 @@ +error[E0275]: overflow evaluating the requirement `<() as B>::Assoc == _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`.