Auto merge of #115979 - GuillaumeGomez:rollup-06ujzgh, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #113383 (style-guide: Add section on bugs, and resolving bugs) - #115499 (rustc_target/riscv: Fix passing of transparent unions with only one non-ZST member) - #115801 (Detect cycle errors hidden by opaques during monomorphization) - #115947 (Custom code classes in docs warning) - #115957 (fix mismatched symbols) - #115958 (explain mysterious addition in float minimum/maximum) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ac5ac4754a
@ -1118,6 +1118,10 @@ fn is_tuple(this: TyAndLayout<'tcx>) -> bool {
|
||||
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.
|
||||
|
@ -89,6 +89,17 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ fn ty_and_layout_pointee_info_at(
|
||||
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 @@ pub fn is_unit<C>(self) -> bool
|
||||
Ty::is_unit(self)
|
||||
}
|
||||
|
||||
pub fn is_transparent<C>(self) -> bool
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C>,
|
||||
{
|
||||
Ty::is_transparent(self)
|
||||
}
|
||||
|
||||
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C>,
|
||||
|
@ -3,10 +3,13 @@
|
||||
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?
|
||||
|
@ -957,6 +957,7 @@ pub fn minimum(self, other: f32) -> 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
|
||||
}
|
||||
}
|
||||
|
@ -968,6 +968,7 @@ pub fn minimum(self, other: f64) -> 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
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -868,7 +868,7 @@ fn error_invalid_codeblock_attr_with_help(
|
||||
|
||||
#[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 @@ fn parse_in_attribute_block(&mut self) -> Option<LangStringToken<'a>> {
|
||||
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 @@ fn parse_outside_attribute_block(&mut self, start: usize) -> Option<LangStringTo
|
||||
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 @@ fn parse_outside_attribute_block(&mut self, start: usize) -> Option<LangStringTo
|
||||
} 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 @@ fn parse_outside_attribute_block(&mut self, start: usize) -> Option<LangStringTo
|
||||
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 @@ fn next(&mut self) -> Option<Self::Item> {
|
||||
}
|
||||
}
|
||||
|
||||
fn tokens(string: &str) -> impl Iterator<Item = LangStringToken<'_>> {
|
||||
// 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 @@ fn parse(
|
||||
|
||||
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<Item = LangStringToken<'_>>| {
|
||||
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::<Edition>().ok();
|
||||
}
|
||||
LangStringToken::LangToken(x)
|
||||
if allow_error_code_check && x.starts_with('E') && x.len() == 5 =>
|
||||
{
|
||||
if x[1..].parse::<u32>().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::<Edition>().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::<u32>().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
|
||||
|
@ -226,13 +226,28 @@ fn t(lg: LangString) {
|
||||
..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()],
|
||||
|
@ -21,6 +21,10 @@
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -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)}
|
||||
|
@ -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
|
||||
|
||||
|
@ -8,3 +8,8 @@
|
||||
//~| NOTE see issue #79483 <https://github.com/rust-lang/rust/issues/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;
|
||||
|
@ -10,7 +10,6 @@
|
||||
// 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 @@ mod $name {
|
||||
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>);
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,38 @@
|
||||
// edition: 2021
|
||||
// build-fail
|
||||
//~^^ ERROR overflow evaluating the requirement `<A as Second>::{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<C> Second for C
|
||||
where
|
||||
C: First,
|
||||
{
|
||||
async fn second(self) {
|
||||
self.first().await.second().await;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
error[E0275]: overflow evaluating the requirement `<A as Second>::{opaque#0} == _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
@ -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<Output = ()>;
|
||||
|
||||
fn recur(self) -> Self::Recur;
|
||||
}
|
||||
|
||||
async fn recur(t: impl Recur) {
|
||||
t.recur().await;
|
||||
}
|
||||
|
||||
impl Recur for () {
|
||||
type Recur = impl Future<Output = ()>;
|
||||
|
||||
fn recur(self) -> Self::Recur {
|
||||
async move { recur(self).await; }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
recur(());
|
||||
}
|
@ -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`.
|
@ -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<T: A> B for T {
|
||||
type Assoc = impl Sized;
|
||||
|
||||
fn test() -> <Self as B>::Assoc {
|
||||
<T as A>::test()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<() as A>::test();
|
||||
}
|
||||
|
||||
impl<T: B> A for T {
|
||||
type Assoc = impl Sized;
|
||||
|
||||
fn test() -> <Self as A>::Assoc {
|
||||
<T as B>::test()
|
||||
}
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user