From a6446c53fe8be6692b07e121b831c3db770ff94a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Mar 2023 10:06:42 -0700 Subject: [PATCH 01/14] rustdoc: fix type search index for `fn() -> &T where T: Trait` --- src/librustdoc/html/render/search_index.rs | 7 ++++++- tests/rustdoc-js/where-clause.js | 7 ++++++- tests/rustdoc-js/where-clause.rs | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e22ac6ec19b00..483137f4c3561 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -465,7 +465,7 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>( } // First, check if it's "Self". - let arg = if let Some(self_) = self_ { + let mut arg = if let Some(self_) = self_ { match &*arg { Type::BorrowedRef { type_, .. } if type_.is_self_type() => self_, type_ if type_.is_self_type() => self_, @@ -475,6 +475,11 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>( arg }; + // strip references from the argument type + while let Type::BorrowedRef { type_, .. } = &*arg { + arg = &*type_; + } + // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. if let Type::Generic(arg_s) = *arg { diff --git a/tests/rustdoc-js/where-clause.js b/tests/rustdoc-js/where-clause.js index 6cb42a455a369..4112f08fb0a5f 100644 --- a/tests/rustdoc-js/where-clause.js +++ b/tests/rustdoc-js/where-clause.js @@ -1,4 +1,4 @@ -const QUERY = ['trait', '-> trait', 't1, t2']; +const QUERY = ['trait', '-> trait', 't1, t2', '-> shazam']; const EXPECTED = [ { @@ -16,4 +16,9 @@ const EXPECTED = [ { 'path': 'where_clause', 'name': 'presto' }, ], }, + { + 'others': [ + { 'path': 'where_clause', 'name': 'bippety' }, + ], + }, ]; diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs index 808561feee227..f8bdc072216e6 100644 --- a/tests/rustdoc-js/where-clause.rs +++ b/tests/rustdoc-js/where-clause.rs @@ -14,3 +14,9 @@ pub trait T2<'a, T> { } pub fn presto(_: A, _: B) where A: T1, B: for <'b> T2<'b, Nested> {} + +pub trait Shazam {} + +pub fn bippety() -> &'static X where X: Shazam { + panic!() +} From 44813e038c62ac975f4efaf8fb588949d24528af Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 7 Mar 2023 11:21:12 -0700 Subject: [PATCH 02/14] rustdoc: fix type search when more than one `where` clause applies --- src/librustdoc/html/render/search_index.rs | 2 +- .../rustdoc-js-std/option-type-signatures.js | 23 ++++++++++++++----- tests/rustdoc-js/where-clause.js | 8 ++++++- tests/rustdoc-js/where-clause.rs | 8 +++++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 483137f4c3561..84213182d0ac1 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -484,7 +484,7 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>( // for its bounds. if let Type::Generic(arg_s) = *arg { // First we check if the bounds are in a `where` predicate... - if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { + for where_pred in generics.where_predicates.iter().filter(|g| match g { WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s, _ => false, }) { diff --git a/tests/rustdoc-js-std/option-type-signatures.js b/tests/rustdoc-js-std/option-type-signatures.js index dee4819e81a9f..6bf421a213560 100644 --- a/tests/rustdoc-js-std/option-type-signatures.js +++ b/tests/rustdoc-js-std/option-type-signatures.js @@ -1,7 +1,18 @@ -const QUERY = 'option, fnonce -> option'; +const QUERY = [ + 'option, fnonce -> option', + 'option -> default', +]; -const EXPECTED = { - 'others': [ - { 'path': 'std::option::Option', 'name': 'map' }, - ], -}; +const EXPECTED = [ + { + 'others': [ + { 'path': 'std::option::Option', 'name': 'map' }, + ], + }, + { + 'others': [ + { 'path': 'std::option::Option', 'name': 'unwrap_or_default' }, + { 'path': 'std::option::Option', 'name': 'get_or_insert_default' }, + ], + }, +]; diff --git a/tests/rustdoc-js/where-clause.js b/tests/rustdoc-js/where-clause.js index 4112f08fb0a5f..86254a80e20f3 100644 --- a/tests/rustdoc-js/where-clause.js +++ b/tests/rustdoc-js/where-clause.js @@ -1,4 +1,4 @@ -const QUERY = ['trait', '-> trait', 't1, t2', '-> shazam']; +const QUERY = ['trait', '-> trait', 't1, t2', '-> shazam', 'drizzel -> shazam']; const EXPECTED = [ { @@ -19,6 +19,12 @@ const EXPECTED = [ { 'others': [ { 'path': 'where_clause', 'name': 'bippety' }, + { 'path': 'where_clause::Drizzel', 'name': 'boppety' }, + ], + }, + { + 'others': [ + { 'path': 'where_clause::Drizzel', 'name': 'boppety' }, ], }, ]; diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs index f8bdc072216e6..56c01019fb69f 100644 --- a/tests/rustdoc-js/where-clause.rs +++ b/tests/rustdoc-js/where-clause.rs @@ -20,3 +20,11 @@ pub trait Shazam {} pub fn bippety() -> &'static X where X: Shazam { panic!() } + +pub struct Drizzel(T); + +impl Drizzel { + pub fn boppety(&self) -> &T where T: Shazam { + panic!(); + } +} From 50f7520526c72beab648798255e5e7a00a38f8ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Mar 2023 20:28:00 +0100 Subject: [PATCH 03/14] rustdoc: DocFS: Replace rayon with threadpool and enable it for all targets --- Cargo.lock | 11 ++++++++++- src/librustdoc/Cargo.toml | 4 +--- src/librustdoc/docfs.rs | 27 +++++++++++++++++++++------ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51332919fe755..522d91aed34e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5457,13 +5457,13 @@ dependencies = [ "itertools", "minifier", "once_cell", - "rayon", "regex", "rustdoc-json-types", "serde", "serde_json", "smallvec", "tempfile", + "threadpool", "tracing", "tracing-subscriber", "tracing-tree", @@ -6208,6 +6208,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "tidy" version = "0.1.0" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 6ca6edfd3c9fe..29912b95703b2 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -20,15 +20,13 @@ smallvec = "1.8.1" tempfile = "3" tracing = "0.1" tracing-tree = "0.2.0" +threadpool = "1.8.1" [dependencies.tracing-subscriber] version = "0.3.3" default-features = false features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] -[target.'cfg(windows)'.dependencies] -rayon = "1.5.1" - [dev-dependencies] expect-test = "1.4.0" diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index be066bdafa14a..59393697dfec3 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -9,11 +9,14 @@ //! needs to read-after-write from a file, then it would be added to this //! abstraction. +use std::cmp::max; use std::fs; use std::io; use std::path::{Path, PathBuf}; use std::string::ToString; use std::sync::mpsc::Sender; +use std::thread::available_parallelism; +use threadpool::ThreadPool; pub(crate) trait PathError { fn new>(e: S, path: P) -> Self @@ -24,11 +27,21 @@ pub(crate) trait PathError { pub(crate) struct DocFS { sync_only: bool, errors: Option>, + pool: ThreadPool, } impl DocFS { pub(crate) fn new(errors: Sender) -> DocFS { - DocFS { sync_only: false, errors: Some(errors) } + const MINIMUM_NB_THREADS: usize = 2; + DocFS { + sync_only: false, + errors: Some(errors), + pool: ThreadPool::new( + available_parallelism() + .map(|nb| max(nb.get(), MINIMUM_NB_THREADS)) + .unwrap_or(MINIMUM_NB_THREADS), + ), + } } pub(crate) fn set_sync_only(&mut self, sync_only: bool) { @@ -54,12 +67,11 @@ impl DocFS { where E: PathError, { - #[cfg(windows)] if !self.sync_only { // A possible future enhancement after more detailed profiling would // be to create the file sync so errors are reported eagerly. let sender = self.errors.clone().expect("can't write after closing"); - rayon::spawn(move || { + self.pool.execute(move || { fs::write(&path, contents).unwrap_or_else(|e| { sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| { panic!("failed to send error on \"{}\"", path.display()) @@ -70,9 +82,12 @@ impl DocFS { fs::write(&path, contents).map_err(|e| E::new(e, path))?; } - #[cfg(not(windows))] - fs::write(&path, contents).map_err(|e| E::new(e, path))?; - Ok(()) } } + +impl Drop for DocFS { + fn drop(&mut self) { + self.pool.join(); + } +} From e482701998aa63915f5144562008a8f6388dcb6e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 14 Mar 2023 22:56:20 +0000 Subject: [PATCH 04/14] Assert def-kind is correct for alias types --- compiler/rustc_middle/src/ty/context.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8dd8f95fcc714..43203a9767184 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -71,6 +71,7 @@ use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; use std::any::Any; +use std::assert_matches::debug_assert_matches; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -2049,6 +2050,12 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { + debug_assert_matches!( + (kind, self.def_kind(alias_ty.def_id)), + (ty::Opaque, DefKind::OpaqueTy) + | (ty::Projection, DefKind::AssocTy | DefKind::AssocConst) + | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + ); self.mk_ty_from_kind(Alias(kind, alias_ty)) } From cf6424e88123b5e9ee251dddd260812b5f6b20cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 14 Mar 2023 23:12:42 +0000 Subject: [PATCH 05/14] Don't make projection tys out of anon consts --- compiler/rustc_infer/src/infer/at.rs | 24 ++++--------------- .../src/infer/error_reporting/mod.rs | 4 ++++ compiler/rustc_infer/src/infer/mod.rs | 1 + compiler/rustc_middle/src/ty/context.rs | 2 +- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 7d9bae735e55d..d1710f6cede95 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -84,7 +84,6 @@ impl<'tcx> InferCtxt<'tcx> { pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -233,7 +232,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let trace = ToTrace::to_trace(self.infcx.tcx, self.cause, a_is_expected, a, b); + let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b); Trace { at: self, trace, a_is_expected } } } @@ -306,7 +305,6 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -314,10 +312,10 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { ) -> TypeTrace<'tcx> { match (a, b) { (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, trait_ref_a, trait_ref_b) + ToTrace::to_trace(cause, a_is_expected, trait_ref_a, trait_ref_b) } (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, ty_a, ty_b) + ToTrace::to_trace(cause, a_is_expected, ty_a, ty_b) } (ImplSubject::Trait(_), ImplSubject::Inherent(_)) | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => { @@ -329,7 +327,6 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -344,7 +341,6 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -356,7 +352,6 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { impl<'tcx> ToTrace<'tcx> for Const<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -371,7 +366,6 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -399,7 +393,6 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -411,7 +404,6 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -426,7 +418,6 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, @@ -441,24 +432,17 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { fn to_trace( - tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, b: Self, ) -> TypeTrace<'tcx> { - let a_ty = tcx.mk_projection(a.def_id, a.substs); - let b_ty = tcx.mk_projection(b.def_id, b.substs); - TypeTrace { - cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())), - } + TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) } } } impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 8a2b800af0e81..ac4986a577c6d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1568,6 +1568,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { (false, Mismatch::Fixed("trait")) } + ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => { + (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id))) + } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), }; let Some(vals) = self.values_str(values) else { @@ -2124,6 +2127,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { match values { infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Terms(exp_found) => self.expected_found_str_term(exp_found), + infer::Aliases(exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4a834957959db..0b207e329f6e6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -338,6 +338,7 @@ pub struct InferCtxt<'tcx> { pub enum ValuePairs<'tcx> { Regions(ExpectedFound>), Terms(ExpectedFound>), + Aliases(ExpectedFound>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), Sigs(ExpectedFound>), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 43203a9767184..7f1b65a08d963 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2053,7 +2053,7 @@ impl<'tcx> TyCtxt<'tcx> { debug_assert_matches!( (kind, self.def_kind(alias_ty.def_id)), (ty::Opaque, DefKind::OpaqueTy) - | (ty::Projection, DefKind::AssocTy | DefKind::AssocConst) + | (ty::Projection, DefKind::AssocTy) | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) ); self.mk_ty_from_kind(Alias(kind, alias_ty)) From bd1732240b586733d8d9fb47cf9ef4cfc299c22e Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Fri, 10 Mar 2023 21:29:45 +1300 Subject: [PATCH 06/14] error-msg: impl better suggestion for `E0532` --- .../rustc_resolve/src/late/diagnostics.rs | 48 ++++++++++++------- tests/ui/issues/issue-19086.stderr | 2 +- tests/ui/pattern/issue-106862.fixed | 44 +++++++++++++++++ tests/ui/pattern/issue-106862.rs | 44 +++++++++++++++++ tests/ui/pattern/issue-106862.stderr | 48 +++++++++++++++++++ 5 files changed, 169 insertions(+), 17 deletions(-) create mode 100644 tests/ui/pattern/issue-106862.fixed create mode 100644 tests/ui/pattern/issue-106862.rs create mode 100644 tests/ui/pattern/issue-106862.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 805c2ff280d8b..df7681dc4267b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1289,25 +1289,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => { let span = find_span(&source, err); err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here")); - let (tail, descr, applicability) = match source { - PathSource::Pat | PathSource::TupleStruct(..) => { - ("", "pattern", Applicability::MachineApplicable) - } - _ => (": val", "literal", Applicability::HasPlaceholders), - }; + let (tail, descr, applicability, old_fields) = match source { + PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None), + PathSource::TupleStruct(_, args) => ( + "", + "pattern", + Applicability::MachineApplicable, + Some( + args.iter() + .map(|a| self.r.tcx.sess.source_map().span_to_snippet(*a).ok()) + .collect::>>(), + ), + ), + _ => (": val", "literal", Applicability::HasPlaceholders, None), + }; let field_ids = self.r.field_def_ids(def_id); let (fields, applicability) = match field_ids { - Some(field_ids) => ( - field_ids - .iter() - .map(|&field_id| { - format!("{}{tail}", self.r.tcx.item_name(field_id)) - }) - .collect::>() - .join(", "), - applicability, - ), + Some(field_ids) => { + let fields = field_ids.iter().map(|&id| self.r.tcx.item_name(id)); + + let fields = if let Some(old_fields) = old_fields { + fields + .enumerate() + .map(|(idx, new)| (new, old_fields.get(idx))) + .map(|(new, old)| { + let new = new.to_ident_string(); + if let Some(Some(old)) = old && new != *old { format!("{}: {}", new, old) } else { new } + }) + .collect::>() + } else { + fields.map(|f| format!("{f}{tail}")).collect::>() + }; + + (fields.join(", "), applicability) + } None => ("/* fields */".to_string(), Applicability::HasPlaceholders), }; let pad = match field_ids { diff --git a/tests/ui/issues/issue-19086.stderr b/tests/ui/issues/issue-19086.stderr index a3c06a7251115..90d0bb4065543 100644 --- a/tests/ui/issues/issue-19086.stderr +++ b/tests/ui/issues/issue-19086.stderr @@ -5,7 +5,7 @@ LL | FooB { x: i32, y: i32 } | ----------------------- `FooB` defined here ... LL | FooB(a, b) => println!("{} {}", a, b), - | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }` + | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }` error: aborting due to previous error diff --git a/tests/ui/pattern/issue-106862.fixed b/tests/ui/pattern/issue-106862.fixed new file mode 100644 index 0000000000000..9b27a61ffd069 --- /dev/null +++ b/tests/ui/pattern/issue-106862.fixed @@ -0,0 +1,44 @@ +// run-rustfix + +#![allow(unused)] + +use Foo::{FooB, FooA}; + +enum Foo { + FooA { opt_x: Option, y: i32 }, + FooB { x: i32, y: i32 } +} + +fn main() { + let f = FooB { x: 3, y: 4 }; + + match f { + FooB { x: a, y: b } => println!("{} {}", a, b), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooB { x, y } => println!("{} {}", x, y), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooA { opt_x: Some(x), y } => println!("{} {}", x, y), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooA` + _ => (), + } + + match f { + FooB { x: a, y: _ } => println!("{}", a), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooB { x, y } => (), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } +} diff --git a/tests/ui/pattern/issue-106862.rs b/tests/ui/pattern/issue-106862.rs new file mode 100644 index 0000000000000..590430a784314 --- /dev/null +++ b/tests/ui/pattern/issue-106862.rs @@ -0,0 +1,44 @@ +// run-rustfix + +#![allow(unused)] + +use Foo::{FooB, FooA}; + +enum Foo { + FooA { opt_x: Option, y: i32 }, + FooB { x: i32, y: i32 } +} + +fn main() { + let f = FooB { x: 3, y: 4 }; + + match f { + FooB(a, b) => println!("{} {}", a, b), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooB(x, y) => println!("{} {}", x, y), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooA(Some(x), y) => println!("{} {}", x, y), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooA` + _ => (), + } + + match f { + FooB(a, _, _) => println!("{}", a), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } + + match f { + FooB() => (), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + _ => (), + } +} diff --git a/tests/ui/pattern/issue-106862.stderr b/tests/ui/pattern/issue-106862.stderr new file mode 100644 index 0000000000000..27f8ac97284eb --- /dev/null +++ b/tests/ui/pattern/issue-106862.stderr @@ -0,0 +1,48 @@ +error[E0532]: expected tuple struct or tuple variant, found variant `FooB` + --> $DIR/issue-106862.rs:16:9 + | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... +LL | FooB(a, b) => println!("{} {}", a, b), + | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }` + +error[E0532]: expected tuple struct or tuple variant, found variant `FooB` + --> $DIR/issue-106862.rs:22:9 + | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... +LL | FooB(x, y) => println!("{} {}", x, y), + | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }` + +error[E0532]: expected tuple struct or tuple variant, found variant `FooA` + --> $DIR/issue-106862.rs:28:9 + | +LL | FooA { opt_x: Option, y: i32 }, + | ----------------------------------- `FooA` defined here +... +LL | FooA(Some(x), y) => println!("{} {}", x, y), + | ^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooA { opt_x: Some(x), y }` + +error[E0532]: expected tuple struct or tuple variant, found variant `FooB` + --> $DIR/issue-106862.rs:34:9 + | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... +LL | FooB(a, _, _) => println!("{}", a), + | ^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: _ }` + +error[E0532]: expected tuple struct or tuple variant, found variant `FooB` + --> $DIR/issue-106862.rs:40:9 + | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... +LL | FooB() => (), + | ^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0532`. From 35103fe8ab588348be8cb679c8ced006b946755f Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 11 Mar 2023 18:28:05 +1300 Subject: [PATCH 07/14] error-msg: expand suggestion for unused lint --- compiler/rustc_lint/src/lints.rs | 22 ++++++------ compiler/rustc_lint/src/unused.rs | 31 +++++++---------- .../cfg-attr-multi-true.stderr | 4 +++ tests/ui/lint/fn_must_use.stderr | 28 +++++++++++++++ .../lint/unused/must-use-box-from-raw.stderr | 4 +++ tests/ui/lint/unused/must_use-unit.stderr | 9 +++++ tests/ui/lint/unused/unused-async.stderr | 20 +++++++++++ tests/ui/lint/unused/unused-result.stderr | 17 ++++++++++ .../unused/unused_attributes-must_use.stderr | 34 +++++++++++++++++++ 9 files changed, 138 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20ab0af585651..308c02929ca42 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1390,7 +1390,7 @@ pub struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, - #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")] + #[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")] pub suggestion: Span, } @@ -1434,17 +1434,15 @@ pub struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] -pub enum UnusedDefSuggestion { - #[suggestion( - lint_suggestion, - style = "verbose", - code = "let _ = ", - applicability = "machine-applicable" - )] - Default { - #[primary_span] - span: Span, - }, +#[suggestion( + lint_suggestion, + style = "verbose", + code = "let _ = ", + applicability = "maybe-incorrect" +)] +pub struct UnusedDefSuggestion { + #[primary_span] + pub span: Span, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 2fab82d55cd47..faca61fc29bf9 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); let type_lint_emitted_or_suppressed = match must_use_result { Some(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1); + emit_must_use_untranslated(cx, &path, "", "", 1, false); true } None => false, @@ -358,6 +358,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre_path, descr_post_path, 1, + false, ) }) .is_some() @@ -370,6 +371,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre: &str, descr_post: &str, plural_len: usize, + is_inner: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -377,20 +379,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { MustUsePath::Suppressed => {} MustUsePath::Boxed(path) => { let descr_pre = &format!("{}boxed ", descr_pre); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::Opaque(path) => { let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TraitObject(path) => { let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); } MustUsePath::TupleElement(elems) => { for (index, path) in elems { let descr_post = &format!(" in tuple element {}", index); - emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + emit_must_use_untranslated( + cx, path, descr_pre, descr_post, plural_len, true, + ); } } MustUsePath::Array(path, len) => { @@ -401,6 +405,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre, descr_post, plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), + true, ); } MustUsePath::Closure(span) => { @@ -418,19 +423,6 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { - let suggestion = if matches!( - cx.tcx.get_diagnostic_name(*def_id), - Some(sym::add) - | Some(sym::sub) - | Some(sym::mul) - | Some(sym::div) - | Some(sym::rem) - | Some(sym::neg), - ) { - Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() }) - } else { - None - }; cx.emit_spanned_lint( UNUSED_MUST_USE, *span, @@ -440,7 +432,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, - suggestion, + suggestion: (!is_inner) + .then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }), }, ); } diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr index fbfcd45652f19..123ce71727f67 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr @@ -35,6 +35,10 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = MustUseDeprecated::new(); + | +++++++ warning: 5 warnings emitted diff --git a/tests/ui/lint/fn_must_use.stderr b/tests/ui/lint/fn_must_use.stderr index 657f23c60856f..e88c1a9b8a9b9 100644 --- a/tests/ui/lint/fn_must_use.stderr +++ b/tests/ui/lint/fn_must_use.stderr @@ -10,12 +10,21 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = need_to_use_this_value(); + | +++++++ warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used --> $DIR/fn_must_use.rs:60:5 | LL | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = m.need_to_use_this_method_value(); + | +++++++ warning: unused return value of `EvenNature::is_even` that must be used --> $DIR/fn_must_use.rs:61:5 @@ -24,24 +33,43 @@ LL | m.is_even(); // trait method! | ^^^^^^^^^^^ | = note: no side effects +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = m.is_even(); // trait method! + | +++++++ warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used --> $DIR/fn_must_use.rs:64:5 | LL | MyStruct::need_to_use_this_associated_function_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = MyStruct::need_to_use_this_associated_function_value(); + | +++++++ warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:70:5 | LL | 2.eq(&3); | ^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 2.eq(&3); + | +++++++ warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:71:5 | LL | m.eq(&n); | ^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = m.eq(&n); + | +++++++ warning: unused comparison that must be used --> $DIR/fn_must_use.rs:74:5 diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr index 47ab613bec21c..4898db7fe3ddd 100644 --- a/tests/ui/lint/unused/must-use-box-from-raw.stderr +++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr @@ -10,6 +10,10 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = Box::from_raw(ptr); + | +++++++ warning: 1 warning emitted diff --git a/tests/ui/lint/unused/must_use-unit.stderr b/tests/ui/lint/unused/must_use-unit.stderr index 9fcbc5074ea80..993a19e5f04ed 100644 --- a/tests/ui/lint/unused/must_use-unit.stderr +++ b/tests/ui/lint/unused/must_use-unit.stderr @@ -9,12 +9,21 @@ note: the lint level is defined here | LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo(); + | +++++++ error: unused return value of `bar` that must be used --> $DIR/must_use-unit.rs:15:5 | LL | bar(); | ^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = bar(); + | +++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr index 4bcb26dc16586..1c3702ba265c0 100644 --- a/tests/ui/lint/unused/unused-async.stderr +++ b/tests/ui/lint/unused/unused-async.stderr @@ -16,12 +16,22 @@ error: unused return value of `foo` that must be used | LL | foo(); | ^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo(); + | +++++++ error: unused output of future returned by `foo` that must be used --> $DIR/unused-async.rs:33:5 | LL | foo().await; | ^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo().await; + | +++++++ error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:34:5 @@ -36,12 +46,22 @@ error: unused return value of `bar` that must be used | LL | bar(); | ^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = bar(); + | +++++++ error: unused output of future returned by `bar` that must be used --> $DIR/unused-async.rs:36:5 | LL | bar().await; | ^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = bar().await; + | +++++++ error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:37:5 diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr index 4e1ba1fd9595f..f42995a65d13e 100644 --- a/tests/ui/lint/unused/unused-result.stderr +++ b/tests/ui/lint/unused/unused-result.stderr @@ -9,6 +9,10 @@ note: the lint level is defined here | LL | #![deny(unused_results, unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo::(); + | +++++++ error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:22:5 @@ -17,6 +21,10 @@ LL | foo::(); | ^^^^^^^^^^^^^^^^^^^ | = note: some message +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo::(); + | +++++++ error: unused result of type `isize` --> $DIR/unused-result.rs:34:5 @@ -35,6 +43,11 @@ error: unused `MustUse` that must be used | LL | foo::(); | ^^^^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo::(); + | +++++++ error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:36:5 @@ -43,6 +56,10 @@ LL | foo::(); | ^^^^^^^^^^^^^^^^^^^ | = note: some message +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo::(); + | +++++++ error: aborting due to 5 previous errors diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr index 0f699429e0243..9633767c44287 100644 --- a/tests/ui/lint/unused/unused_attributes-must_use.stderr +++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr @@ -146,42 +146,76 @@ note: the lint level is defined here | LL | #![deny(unused_attributes, unused_must_use)] | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = X; + | +++++++ error: unused `Y` that must be used --> $DIR/unused_attributes-must_use.rs:104:5 | LL | Y::Z; | ^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = Y::Z; + | +++++++ error: unused `U` that must be used --> $DIR/unused_attributes-must_use.rs:105:5 | LL | U { unit: () }; | ^^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = U { unit: () }; + | +++++++ error: unused return value of `U::method` that must be used --> $DIR/unused_attributes-must_use.rs:106:5 | LL | U::method(); | ^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = U::method(); + | +++++++ error: unused return value of `foo` that must be used --> $DIR/unused_attributes-must_use.rs:107:5 | LL | foo(); | ^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foo(); + | +++++++ error: unused return value of `foreign_foo` that must be used --> $DIR/unused_attributes-must_use.rs:110:9 | LL | foreign_foo(); | ^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = foreign_foo(); + | +++++++ error: unused return value of `Use::get_four` that must be used --> $DIR/unused_attributes-must_use.rs:118:5 | LL | ().get_four(); | ^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = ().get_four(); + | +++++++ error: aborting due to 28 previous errors From d3d537b9728697da09b974fd9ac76a14197de514 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Mar 2023 10:21:20 +0000 Subject: [PATCH 08/14] Exhaustively match over all alias kinds --- .../src/traits/project.rs | 22 ++++++++------- .../src/traits/query/normalize.rs | 27 ++++++++++++------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 01075d7c55aee..7385c74389eb8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -467,6 +467,11 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx return ty; } + let (kind, data) = match *ty.kind() { + ty::Alias(kind, alias_ty) => (kind, alias_ty), + _ => return ty.super_fold_with(self), + }; + // We try to be a little clever here as a performance optimization in // cases where there are nested projections under binders. // For example: @@ -490,13 +495,11 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // replace bound vars if the current type is a `Projection` and we need // to make sure we don't forget to fold the substs regardless. - match *ty.kind() { + match kind { // This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) - if !substs.has_escaping_bound_vars() => - { + ty::Opaque if !data.substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.super_fold_with(self), @@ -512,8 +515,8 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ); } - let substs = substs.fold_with(self); - let generic_ty = self.interner().type_of(def_id); + let substs = data.substs.fold_with(self); + let generic_ty = self.interner().type_of(data.def_id); let concrete_ty = generic_ty.subst(self.interner(), substs); self.depth += 1; let folded_ty = self.fold_ty(concrete_ty); @@ -522,8 +525,9 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx } } } + ty::Opaque => ty.super_fold_with(self), - ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => { + ty::Projection if !data.has_escaping_bound_vars() => { // This branch is *mostly* just an optimization: when we don't // have escaping bound vars, we don't need to replace them with // placeholders (see branch below). *Also*, we know that we can @@ -562,7 +566,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx normalized_ty.ty().unwrap() } - ty::Alias(ty::Projection, data) => { + ty::Projection => { // If there are escaping bound vars, we temporarily replace the // bound vars with placeholders. Note though, that in the case // that we still can't project for whatever reason (e.g. self @@ -611,8 +615,6 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ); normalized_ty } - - _ => ty.super_fold_with(self), } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b0cec3ce7a3ea..45307a85a31c9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> return Ok(*ty); } + let (kind, data) = match *ty.kind() { + ty::Alias(kind, data) => (kind, data), + _ => { + let res = ty.try_super_fold_with(self)?; + self.cache.insert(ty, res); + return Ok(res); + } + }; + // See note in `rustc_trait_selection::traits::project` about why we // wait to fold the substs. // Wrap this in a closure so we don't accidentally return from the outer function - let res = match *ty.kind() { + let res = match kind { // This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) - if !substs.has_escaping_bound_vars() => - { + ty::Opaque if !data.substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.try_super_fold_with(self)?, Reveal::All => { - let substs = substs.try_fold_with(self)?; + let substs = data.substs.try_fold_with(self)?; let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { // A closure or generator may have itself as in its upvars. @@ -228,7 +235,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> return ty.try_super_fold_with(self); } - let generic_ty = self.interner().type_of(def_id); + let generic_ty = self.interner().type_of(data.def_id); let concrete_ty = generic_ty.subst(self.interner(), substs); self.anon_depth += 1; if concrete_ty == ty { @@ -248,7 +255,9 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> } } - ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => { + ty::Opaque => ty.try_super_fold_with(self)?, + + ty::Projection if !data.has_escaping_bound_vars() => { // This branch is just an optimization: when we don't have escaping bound vars, // we don't need to replace them with placeholders (see branch below). @@ -297,7 +306,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> } } - ty::Alias(ty::Projection, data) => { + ty::Projection => { // See note in `rustc_trait_selection::traits::project` let tcx = self.infcx.tcx; @@ -353,8 +362,6 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> res } } - - _ => ty.try_super_fold_with(self)?, }; self.cache.insert(ty, res); From d87fbb918c5a9d3dc7f8d1d801fd17a622484a85 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 8 Mar 2023 08:46:15 +0000 Subject: [PATCH 09/14] Deduplicate logic between projection normalization with and without escaping bound vars --- .../src/traits/query/normalize.rs | 80 +++++-------------- 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 45307a85a31c9..a986a9b6a71b1 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -257,62 +257,20 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> ty::Opaque => ty.try_super_fold_with(self)?, - ty::Projection if !data.has_escaping_bound_vars() => { - // This branch is just an optimization: when we don't have escaping bound vars, - // we don't need to replace them with placeholders (see branch below). - - let tcx = self.infcx.tcx; - let data = data.try_fold_with(self)?; - - let mut orig_values = OriginalQueryValues::default(); - // HACK(matthewjasper) `'static` is special-cased in selection, - // so we cannot canonicalize it. - let c_data = self - .infcx - .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); - debug!("QueryNormalizer: c_data = {:#?}", c_data); - debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - let result = tcx.normalize_projection_ty(c_data)?; - // We don't expect ambiguity. - if result.is_ambiguous() { - // Rustdoc normalizes possibly not well-formed types, so only - // treat this as a bug if we're not in rustdoc. - if !tcx.sess.opts.actually_rustdoc { - tcx.sess.delay_span_bug( - DUMMY_SP, - format!("unexpected ambiguity: {:?} {:?}", c_data, result), - ); - } - return Err(NoSolution); - } - let InferOk { value: result, obligations } = - self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - )?; - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - - let res = result.normalized_ty; - // `tcx.normalize_projection_ty` may normalize to a type that still has - // unevaluated consts, so keep normalizing here if that's the case. - if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { - res.try_super_fold_with(self)? - } else { - res - } - } - ty::Projection => { // See note in `rustc_trait_selection::traits::project` let tcx = self.infcx.tcx; let infcx = self.infcx; - let (data, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + // Just an optimization: When we don't have escaping bound vars, + // we don't need to replace them with placeholders. + let (data, maps) = if data.has_escaping_bound_vars() { + let (data, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + (data, Some((mapped_regions, mapped_types, mapped_consts))) + } else { + (data, None) + }; let data = data.try_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); @@ -346,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - let res = PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result.normalized_ty, - ); + let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps { + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + ) + } else { + result.normalized_ty + }; // `tcx.normalize_projection_ty` may normalize to a type that still has // unevaluated consts, so keep normalizing here if that's the case. if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { From d2b7604db9d3262fd9fe9ab39efb60652e252448 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 15 Mar 2023 14:00:15 +0100 Subject: [PATCH 10/14] always make `define_opaque_types` explicit --- .../src/coherence/builtin.rs | 11 +- compiler/rustc_hir_analysis/src/lib.rs | 4 +- compiler/rustc_hir_typeck/src/closure.rs | 20 +-- compiler/rustc_hir_typeck/src/coercion.rs | 40 ++++-- compiler/rustc_hir_typeck/src/demand.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 7 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 10 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 14 +- .../src/generator_interior/mod.rs | 8 +- .../rustc_hir_typeck/src/method/confirm.rs | 4 +- compiler/rustc_hir_typeck/src/method/probe.rs | 22 +-- compiler/rustc_infer/src/infer/at.rs | 131 +++++++++++------- .../src/infer/canonical/query_response.rs | 20 ++- compiler/rustc_infer/src/infer/combine.rs | 9 +- compiler/rustc_infer/src/infer/equate.rs | 4 +- compiler/rustc_infer/src/infer/glb.rs | 4 +- compiler/rustc_infer/src/infer/lattice.rs | 6 +- compiler/rustc_infer/src/infer/lub.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 10 +- .../rustc_infer/src/infer/opaque_types.rs | 12 +- compiler/rustc_infer/src/infer/sub.rs | 5 +- .../src/solve/eval_ctxt.rs | 4 +- .../rustc_trait_selection/src/solve/mod.rs | 4 +- .../src/traits/auto_trait.rs | 3 +- .../src/traits/coherence.rs | 37 ++--- .../src/traits/engine.rs | 14 +- .../src/traits/fulfill.rs | 30 ++-- .../src/traits/project.rs | 19 ++- .../src/traits/select/confirmation.rs | 21 ++- .../src/traits/select/mod.rs | 26 ++-- .../src/traits/specialize/mod.rs | 3 +- .../rustc_trait_selection/src/traits/util.rs | 14 +- src/librustdoc/clean/blanket_impl.rs | 5 +- 33 files changed, 307 insertions(+), 224 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5e8f69677cf3d..0e1cf3e6c6a7d 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::{self, RegionResolutionError}; +use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -235,7 +235,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef use rustc_type_ir::sty::TyKind::*; match (source.kind(), target.kind()) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) - if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {} + if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok() + && mutbl_a == *mutbl_b => {} (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (), (&Adt(def_a, substs_a), &Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => @@ -278,7 +279,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } - if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { + if let Ok(ok) = + infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) + { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ @@ -504,7 +507,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // we may have to evaluate constraint // expressions in the course of execution.) // See e.g., #41936. - if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) { + if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) { if ok.obligations.is_empty() { return None; } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 62abcbbdc9f6e..08786fe9b1ef9 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::Node; -use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_macros::fluent_messages; use rustc_middle::middle; use rustc_middle::ty::query::Providers; @@ -165,7 +165,7 @@ fn require_same_types<'tcx>( ) -> bool { let infcx = &tcx.infer_ctxt().build(); let param_env = ty::ParamEnv::empty(); - let errors = match infcx.at(cause, param_env).eq(expected, actual) { + let errors = match infcx.at(cause, param_env).eq(DefineOpaqueTypes::No, expected, actual) { Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 773ac0e40c571..6becf4892acb2 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime}; use rustc_infer::infer::{InferOk, InferResult}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; @@ -563,10 +563,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // Check that E' = S'. let cause = self.misc(hir_ty.span); - let InferOk { value: (), obligations } = self - .at(&cause, self.param_env) - .define_opaque_types(true) - .eq(*expected_ty, supplied_ty)?; + let InferOk { value: (), obligations } = self.at(&cause, self.param_env).eq( + DefineOpaqueTypes::Yes, + *expected_ty, + supplied_ty, + )?; all_obligations.extend(obligations); } @@ -576,10 +577,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_sig.output(), ); let cause = &self.misc(decl.output.span()); - let InferOk { value: (), obligations } = self - .at(cause, self.param_env) - .define_opaque_types(true) - .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; + let InferOk { value: (), obligations } = self.at(cause, self.param_env).eq( + DefineOpaqueTypes::Yes, + expected_sigs.liberated_sig.output(), + supplied_output_ty, + )?; all_obligations.extend(obligations); let inputs = inputs.into_iter().map(|ty| self.resolve_vars_if_possible(ty)); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 00b86890b33f4..3d6274ede8146 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -45,7 +45,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{Coercion, InferOk, InferResult}; +use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ @@ -143,11 +143,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { - let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true); + let at = self.at(&self.cause, self.fcx.param_env); if self.use_lub { - at.lub(b, a) + at.lub(DefineOpaqueTypes::Yes, b, a) } else { - at.sup(b, a) + at.sup(DefineOpaqueTypes::Yes, b, a) .map(|InferOk { value: (), obligations }| InferOk { value: a, obligations }) } }) @@ -175,7 +175,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // so this will have the side-effect of making sure we have no ambiguities // due to `[type error]` and `_` not coercing together. let _ = self.commit_if_ok(|_| { - self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b) + self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b) }); return success(vec![], self.fcx.tcx.ty_error(guar), vec![]); } @@ -1101,9 +1101,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::FnDef(..), ty::FnDef(..)) => { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. - match self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - { + match self.commit_if_ok(|_| { + self.at(cause, self.param_env).lub( + DefineOpaqueTypes::No, + prev_ty, + new_ty, + ) + }) { // We have a LUB of prev_ty and new_ty, just return it. Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)), Err(_) => { @@ -1153,7 +1157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = self .at(cause, self.param_env) .trace(prev_ty, new_ty) - .lub(a_sig, b_sig) + .lub(DefineOpaqueTypes::No, a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. @@ -1237,7 +1241,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) + .commit_if_ok(|_| { + self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty) + }) .map(|ok| self.register_infer_ok_obligations(ok)); } } @@ -1248,8 +1254,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(e) = first_error { Err(e) } else { - self.commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - .map(|ok| self.register_infer_ok_obligations(ok)) + self.commit_if_ok(|_| { + self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty) + }) + .map(|ok| self.register_infer_ok_obligations(ok)) } } Ok(ok) => { @@ -1487,8 +1495,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { assert!(expression_ty.is_unit(), "if let hack without unit type"); fcx.at(cause, fcx.param_env) // needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs - .define_opaque_types(true) - .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty()) + .eq_exp( + DefineOpaqueTypes::Yes, + label_expression_as_expected, + expression_ty, + self.merged_ty(), + ) .map(|infer_ok| { fcx.register_infer_ok_obligations(infer_ok); expression_ty diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0ec10dc9ea32d..f65f16e317d49 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -8,7 +8,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; -use rustc_infer::infer::InferOk; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -113,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option> { - match self.at(cause, self.param_env).define_opaque_types(true).sup(expected, actual) { + match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, actual: Ty<'tcx>, ) -> Option> { - match self.at(cause, self.param_env).define_opaque_types(true).eq(expected, actual) { + match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); None diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7fc4ccb04ee0b..afef331ec1d93 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -36,6 +36,7 @@ use rustc_hir_analysis::astconv::AstConv as _; use rustc_hir_analysis::check::ty_kind_suggestion; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::InferOk; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability; @@ -1683,7 +1684,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, substs); let cause = self.misc(base_expr.span); - match self.at(&cause, self.param_env).sup(target_ty, fru_ty) { + match self.at(&cause, self.param_env).sup( + DefineOpaqueTypes::No, + target_ty, + fru_ty, + ) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index ac73cd7cc6e17..e539693402af9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -19,7 +19,7 @@ use rustc_hir_analysis::astconv::{ }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc_infer::infer::InferResult; +use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = self.tcx.hir().body(body_id).value.span; let ok = self .at(&self.misc(span), self.param_env) - .eq(interior, witness) + .eq(DefineOpaqueTypes::No, interior, witness) .expect("Failed to unify generator interior type"); let mut obligations = ok.obligations; @@ -1341,7 +1341,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This also occurs for an enum variant on a type alias. let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).subst(tcx, substs)); let self_ty = self.normalize(span, self_ty); - match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) { + match self.at(&self.misc(span), self.param_env).eq( + DefineOpaqueTypes::No, + impl_ty, + self_ty, + ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { self.tcx.sess.delay_span_bug( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ea54b76bdec96..7064ff6538487 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -24,8 +24,8 @@ use rustc_hir_analysis::structured_errors::StructuredDiagnostic; use rustc_index::vec::IndexVec; use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::InferOk; use rustc_infer::infer::TypeTrace; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty}; @@ -301,9 +301,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 3. Check if the formal type is a supertype of the checked one // and register any such obligations for future type checks - let supertype_error = self - .at(&self.misc(provided_arg.span), self.param_env) - .sup(formal_input_ty, coerced_ty); + let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup( + DefineOpaqueTypes::No, + formal_input_ty, + coerced_ty, + ); let subtyping_error = match supertype_error { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); @@ -585,7 +587,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Using probe here, since we don't want this subtyping to affect inference. let subtyping_error = self.probe(|_| { - self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err() + self.at(&self.misc(arg_span), self.param_env) + .sup(DefineOpaqueTypes::No, formal_input_ty, coerced_ty) + .err() }); // Same as above: if either the coerce type or the checked type is an error type, diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 2e41c2041f888..9ecc870a70dbd 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -13,7 +13,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; -use rustc_infer::infer::RegionVariableOrigin; +use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin}; use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt}; @@ -327,7 +327,11 @@ pub fn resolve_interior<'a, 'tcx>( ); // Unify the type variable inside the generator with the new witness - match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) { + match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq( + DefineOpaqueTypes::No, + interior, + witness, + ) { Ok(ok) => fcx.register_infer_ok_obligations(ok), _ => bug!("failed to relate {interior} and {witness}"), } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 169f128e0a003..a0aa43deadcfd 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -8,7 +8,7 @@ use rustc_hir_analysis::astconv::generics::{ check_generic_arg_count_for_call, create_substs_for_generic_args, }; use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall}; -use rustc_infer::infer::{self, InferOk}; +use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; @@ -478,7 +478,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { substs, })), ); - match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { + match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3254a93034236..8f31a79e7b393 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -13,6 +13,7 @@ use rustc_hir_analysis::astconv::InferCtxtExt as _; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::TreatProjections; @@ -930,7 +931,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let Some(self_ty) = self_ty { if self .at(&ObligationCause::dummy(), self.param_env) - .sup(fty.inputs()[0], self_ty) + .sup(DefineOpaqueTypes::No, fty.inputs()[0], self_ty) .is_err() { return false; @@ -1436,9 +1437,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { - let _ = self - .at(&ObligationCause::dummy(), self.param_env) - .sup(candidate.xform_self_ty, self_ty); + let _ = self.at(&ObligationCause::dummy(), self.param_env).sup( + DefineOpaqueTypes::No, + candidate.xform_self_ty, + self_ty, + ); match self.select_trait_candidate(trait_ref) { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point @@ -1465,10 +1468,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.probe(|_| { // First check that the self type can be related. - let sub_obligations = match self - .at(&ObligationCause::dummy(), self.param_env) - .sup(probe.xform_self_ty, self_ty) - { + let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup( + DefineOpaqueTypes::No, + probe.xform_self_ty, + self_ty, + ) { Ok(InferOk { obligations, value: () }) => obligations, Err(err) => { debug!("--> cannot relate self-types {:?}", err); @@ -1683,7 +1687,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let ProbeResult::Match = result && self .at(&ObligationCause::dummy(), self.param_env) - .sup(return_ty, xform_ret_ty) + .sup(DefineOpaqueTypes::No, return_ty, xform_ret_ty) .is_err() { result = ProbeResult::BadReturnType; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 7d9bae735e55d..678832fc8d6f4 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -30,16 +30,20 @@ use super::*; use rustc_middle::ty::relate::{Relate, TypeRelation}; use rustc_middle::ty::{Const, ImplSubject}; +/// Whether we should define opaque types or just treat them opaquely. +/// +/// Currently only used to prevent predicate matching from matching anything +/// against opaque types. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum DefineOpaqueTypes { + Yes, + No, +} + pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub cause: &'a ObligationCause<'tcx>, pub param_env: ty::ParamEnv<'tcx>, - /// Whether we should define opaque types - /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, } pub struct Trace<'a, 'tcx> { @@ -55,7 +59,7 @@ impl<'tcx> InferCtxt<'tcx> { cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> At<'a, 'tcx> { - At { infcx: self, cause, param_env, define_opaque_types: false } + At { infcx: self, cause, param_env } } /// Forks the inference context, creating a new inference context with the same inference @@ -93,33 +97,21 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy { } impl<'a, 'tcx> At<'a, 'tcx> { - pub fn define_opaque_types(self, define_opaque_types: bool) -> Self { - Self { define_opaque_types, ..self } - } - - /// Hacky routine for equating two impl headers in coherence. - pub fn eq_impl_headers( - self, - expected: &ty::ImplHeader<'tcx>, - actual: &ty::ImplHeader<'tcx>, - ) -> InferResult<'tcx, ()> { - debug!("eq_impl_header({:?} = {:?})", expected, actual); - match (expected.trait_ref, actual.trait_ref) { - (Some(a_ref), Some(b_ref)) => self.eq(a_ref, b_ref), - (None, None) => self.eq(expected.self_ty, actual.self_ty), - _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), - } - } - /// Makes `a <: b`, where `a` may or may not be expected. /// /// See [`At::trace_exp`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sub_exp(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> + pub fn sub_exp( + self, + define_opaque_types: DefineOpaqueTypes, + a_is_expected: bool, + a: T, + b: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).sub(a, b) + self.trace_exp(a_is_expected, a, b).sub(define_opaque_types, a, b) } /// Makes `actual <: expected`. For example, if type-checking a @@ -129,54 +121,81 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sup(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn sup( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.sub_exp(false, actual, expected) + self.sub_exp(define_opaque_types, false, actual, expected) } /// Makes `expected <: actual`. /// /// See [`At::trace`] and [`Trace::sub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn sub(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn sub( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.sub_exp(true, expected, actual) + self.sub_exp(define_opaque_types, true, expected, actual) } /// Makes `expected <: actual`. /// /// See [`At::trace_exp`] and [`Trace::eq`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn eq_exp(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> + pub fn eq_exp( + self, + define_opaque_types: DefineOpaqueTypes, + a_is_expected: bool, + a: T, + b: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).eq(a, b) + self.trace_exp(a_is_expected, a, b).eq(define_opaque_types, a, b) } /// Makes `expected <: actual`. /// /// See [`At::trace`] and [`Trace::eq`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn eq(self, expected: T, actual: T) -> InferResult<'tcx, ()> + pub fn eq( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq(expected, actual) + self.trace(expected, actual).eq(define_opaque_types, expected, actual) } - pub fn relate(self, expected: T, variance: ty::Variance, actual: T) -> InferResult<'tcx, ()> + pub fn relate( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + variance: ty::Variance, + actual: T, + ) -> InferResult<'tcx, ()> where T: ToTrace<'tcx>, { match variance { - ty::Variance::Covariant => self.sub(expected, actual), - ty::Variance::Invariant => self.eq(expected, actual), - ty::Variance::Contravariant => self.sup(expected, actual), + ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual), + ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual), + ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual), // We could make this make sense but it's not readily // exposed and I don't feel like dealing with it. Note @@ -195,11 +214,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::lub`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn lub(self, expected: T, actual: T) -> InferResult<'tcx, T> + pub fn lub( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { - self.trace(expected, actual).lub(expected, actual) + self.trace(expected, actual).lub(define_opaque_types, expected, actual) } /// Computes the greatest-lower-bound, or mutual subtype, of two @@ -208,11 +232,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// /// See [`At::trace`] and [`Trace::glb`] for a version of /// this method that only requires `T: Relate<'tcx>` - pub fn glb(self, expected: T, actual: T) -> InferResult<'tcx, T> + pub fn glb( + self, + define_opaque_types: DefineOpaqueTypes, + expected: T, + actual: T, + ) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { - self.trace(expected, actual).glb(expected, actual) + self.trace(expected, actual).glb(define_opaque_types, expected, actual) } /// Sets the "trace" values that will be used for @@ -242,13 +271,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a <: b` where `a` may or may not be expected (if /// `a_is_expected` is true, then `a` is expected). #[instrument(skip(self), level = "debug")] - pub fn sub(self, a: T, b: T) -> InferResult<'tcx, ()> + pub fn sub(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .sub(a_is_expected) .relate(a, b) @@ -259,13 +288,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a == b`; the expectation is set by the call to /// `trace()`. #[instrument(skip(self), level = "debug")] - pub fn eq(self, a: T, b: T) -> InferResult<'tcx, ()> + pub fn eq(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .equate(a_is_expected) .relate(a, b) @@ -274,13 +303,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - pub fn lub(self, a: T, b: T) -> InferResult<'tcx, T> + pub fn lub(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .lub(a_is_expected) .relate(a, b) @@ -289,13 +318,13 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - pub fn glb(self, a: T, b: T) -> InferResult<'tcx, T> + pub fn glb(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { - let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types); + let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types); fields .glb(a_is_expected) .relate(a, b) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 90e89a187822d..7c649b3a65649 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -14,7 +14,7 @@ use crate::infer::canonical::{ }; use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; +use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt}; @@ -510,7 +510,7 @@ impl<'tcx> InferCtxt<'tcx> { let b = substitute_value(self.tcx, &result_subst, b); debug!(?a, ?b, "constrain opaque type"); obligations - .extend(self.at(cause, param_env).define_opaque_types(true).eq(a, b)?.obligations); + .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -603,8 +603,11 @@ impl<'tcx> InferCtxt<'tcx> { match (value1.unpack(), value2.unpack()) { (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env) + .eq(DefineOpaqueTypes::Yes, v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2)) if re1.is_erased() && re2.is_erased() => @@ -612,11 +615,14 @@ impl<'tcx> InferCtxt<'tcx> { // no action needed } (GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => { - obligations - .extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations()); + obligations.extend( + self.at(cause, param_env) + .eq(DefineOpaqueTypes::Yes, v1, v2)? + .into_obligations(), + ); } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { - let ok = self.at(cause, param_env).eq(v1, v2)?; + let ok = self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, v1, v2)?; obligations.extend(ok.into_obligations()); } _ => { diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a2332797e8680..bb6fdd2ffc2c9 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -27,7 +27,7 @@ use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; -use super::{InferCtxt, MiscVariable, TypeTrace}; +use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; @@ -52,12 +52,7 @@ pub struct CombineFields<'infcx, 'tcx> { pub cause: Option, pub param_env: ty::ParamEnv<'tcx>, pub obligations: PredicateObligations<'tcx>, - /// Whether we should define opaque types - /// or just treat them opaquely. - /// Currently only used to prevent predicate - /// matching from matching anything against opaque - /// types. - pub define_opaque_types: bool, + pub define_opaque_types: DefineOpaqueTypes, } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 54a62326ef7bd..c92a74b6241a6 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -1,3 +1,4 @@ +use crate::infer::DefineOpaqueTypes; use crate::traits::PredicateObligations; use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir}; @@ -110,7 +111,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + && def_id.is_local() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 49df393d83b3e..5c12351226aa5 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefineOpaqueTypes { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index f377ac1d19e9c..7f4c141b97af2 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -19,7 +19,7 @@ use super::combine::ObligationEmittingRelation; use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::InferCtxt; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::ObligationCause; use rustc_middle::ty::relate::RelateResult; @@ -36,7 +36,7 @@ pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> { fn cause(&self) -> &ObligationCause<'tcx>; - fn define_opaque_types(&self) -> bool; + fn define_opaque_types(&self) -> DefineOpaqueTypes; // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. @@ -110,7 +110,7 @@ where ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if this.define_opaque_types() && def_id.is_local() => + if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() => { this.register_obligations( infcx diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index c871ccb21f8de..dbef42db8f1bf 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -2,8 +2,8 @@ use super::combine::{CombineFields, ObligationEmittingRelation}; use super::lattice::{self, LatticeDir}; -use super::InferCtxt; use super::Subtype; +use super::{DefineOpaqueTypes, InferCtxt}; use crate::traits::{ObligationCause, PredicateObligations}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -142,7 +142,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, Ok(()) } - fn define_opaque_types(&self) -> bool { + fn define_opaque_types(&self) -> DefineOpaqueTypes { self.fields.define_opaque_types } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 66fb1db46185d..2976c145150df 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,3 +1,4 @@ +pub use self::at::DefineOpaqueTypes; pub use self::freshen::TypeFreshener; pub use self::lexical_region_resolve::RegionResolutionError; pub use self::LateBoundRegionConversionTime::*; @@ -729,7 +730,7 @@ impl<'tcx> InferCtxt<'tcx> { &'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, - define_opaque_types: bool, + define_opaque_types: DefineOpaqueTypes, ) -> CombineFields<'a, 'tcx> { CombineFields { infcx: self, @@ -860,7 +861,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok()) } pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool @@ -868,7 +869,7 @@ impl<'tcx> InferCtxt<'tcx> { T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok()) + self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::No, a, b).is_ok()) } #[instrument(skip(self), level = "debug")] @@ -963,7 +964,8 @@ impl<'tcx> InferCtxt<'tcx> { let ty::SubtypePredicate { a_is_expected, a, b } = self.instantiate_binder_with_placeholders(predicate); - let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; + let ok = + self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)?; Ok(ok.unit()) })) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d5c824d4c41c8..ed4bc594d1a54 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,3 +1,5 @@ +use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use super::{DefineOpaqueTypes, InferResult}; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; @@ -16,18 +18,13 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; - use std::ops::ControlFlow; -pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; - mod table; +pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; -use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::InferResult; - /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that /// appear in the return type). @@ -547,8 +544,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(prev) = prev { obligations = self .at(&cause, param_env) - .define_opaque_types(true) - .eq_exp(a_is_expected, prev, hidden_ty)? + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? .obligations; } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 3e8c2052de89d..230cadb11842e 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -1,5 +1,5 @@ use super::combine::{CombineFields, RelationDir}; -use super::{ObligationEmittingRelation, SubregionOrigin}; +use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; @@ -138,7 +138,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types && def_id.is_local() => + if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + && def_id.is_local() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index ca438a103cf34..856f1eec4433b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; @@ -144,7 +144,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) -> Result>>, NoSolution> { self.infcx .at(&ObligationCause::dummy(), param_env) - .eq(lhs, rhs) + .eq(DefineOpaqueTypes::No, lhs, rhs) .map(|InferOk { value: (), obligations }| { obligations.into_iter().map(|o| o.into()).collect() }) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 55d361b120441..a873060687d35 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,7 +19,7 @@ use std::mem; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -268,7 +268,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let InferOk { value: (), obligations } = self .infcx .at(&ObligationCause::dummy(), goal.param_env) - .sub(goal.predicate.a, goal.predicate.b)?; + .sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?; self.evaluate_all_and_make_canonical_response( obligations.into_iter().map(|pred| pred.into()).collect(), ) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1fb8659bb27d3..1870d3a2daf32 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -7,6 +7,7 @@ use crate::errors::UnableToConstructConstantValue; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitableExt; @@ -814,7 +815,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::No,c1, c2) { Ok(_) => (), Err(_) => return false, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index aeaade1d66c2b..bb207b5832ea9 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -17,7 +17,7 @@ use crate::traits::{ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, DefiningAnchor, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; @@ -181,7 +181,7 @@ fn overlap_within_probe<'cx, 'tcx>( let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id); let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id); - let obligations = equate_impl_headers(selcx, &impl1_header, &impl2_header)?; + let obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); if overlap_mode.use_implicit_negative() { @@ -207,20 +207,25 @@ fn overlap_within_probe<'cx, 'tcx>( Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } -fn equate_impl_headers<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - impl1_header: &ty::ImplHeader<'tcx>, - impl2_header: &ty::ImplHeader<'tcx>, +#[instrument(level = "debug", skip(infcx), ret)] +fn equate_impl_headers<'tcx>( + infcx: &InferCtxt<'tcx>, + impl1: &ty::ImplHeader<'tcx>, + impl2: &ty::ImplHeader<'tcx>, ) -> Option> { - // Do `a` and `b` unify? If not, no overlap. - debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header); - selcx - .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .define_opaque_types(true) - .eq_impl_headers(impl1_header, impl2_header) - .map(|infer_ok| infer_ok.obligations) - .ok() + let result = match (impl1.trait_ref, impl2.trait_ref) { + (Some(impl1_ref), Some(impl2_ref)) => infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .eq(DefineOpaqueTypes::Yes, impl1_ref, impl2_ref), + (None, None) => infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq( + DefineOpaqueTypes::Yes, + impl1.self_ty, + impl2.self_ty, + ), + _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), + }; + + result.map(|infer_ok| infer_ok.obligations).ok() } /// Given impl1 and impl2 check if both impls can be satisfied by a common type (including @@ -325,7 +330,7 @@ fn equate<'tcx>( ) -> bool { // do the impls unify? If not, not disjoint. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), impl_env).eq(subject1, subject2) + infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2) else { debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2); return true; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 62d5e50dbc548..8acc31cd410bd 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; -use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::query::Fallible; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, @@ -128,8 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .eq_exp(a_is_expected, a, b) + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, a, b) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -142,8 +141,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .eq(expected, actual) + .eq(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -157,8 +155,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .sub(expected, actual) + .sub(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } @@ -172,8 +169,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { ) -> Result<(), TypeError<'tcx>> { self.infcx .at(cause, param_env) - .define_opaque_types(true) - .sup(expected, actual) + .sup(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 944436ab82f91..1aaadae12ddd9 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -2,6 +2,7 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; @@ -515,7 +516,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) .trace(c1, c2) - .eq(a.substs, b.substs) + .eq(DefineOpaqueTypes::No, a.substs, b.substs) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), @@ -524,8 +525,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } (_, Unevaluated(_)) | (Unevaluated(_), _) => (), (_, _) => { - if let Ok(new_obligations) = - infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) + if let Ok(new_obligations) = infcx + .at(&obligation.cause, obligation.param_env) + .eq(DefineOpaqueTypes::No, c1, c2) { return ProcessResult::Changed(mk_pending( new_obligations.into_obligations(), @@ -565,12 +567,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) - { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + c1, + c2, + ) { Ok(inf_ok) => { ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) } @@ -610,12 +611,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { bug!("AliasEq is only used for new solver") } ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - match self - .selcx - .infcx - .at(&obligation.cause, obligation.param_env) - .eq(ct.ty(), ty) - { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + ct.ty(), + ty, + ) { Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 01075d7c55aee..abc5a5eef73d9 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,6 +28,7 @@ use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ImplSourceBuiltinData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -285,12 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>( ); obligations.extend(new); - match infcx - .at(&obligation.cause, obligation.param_env) - // This is needed to support nested opaque types like `impl Fn() -> impl Trait` - .define_opaque_types(true) - .eq(normalized, actual) - { + // Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait` + match infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::Yes, + normalized, + actual, + ) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); ProjectAndUnifyResult::Holds(obligations) @@ -2064,7 +2065,11 @@ fn confirm_param_env_candidate<'cx, 'tcx>( debug!(?cache_projection, ?obligation_projection); - match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { + match infcx.at(cause, param_env).eq( + DefineOpaqueTypes::No, + cache_projection, + obligation_projection, + ) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ee41d840bae92..3d5dd18f4c1d7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,8 +8,8 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::{ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -177,7 +177,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate, candidate) + .sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -462,7 +462,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation_trait_ref, upcast_trait_ref) + .sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -827,11 +827,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); + // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs self.infcx .at(&obligation.cause, obligation.param_env) - // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs - .define_opaque_types(true) - .sup(obligation_trait_ref, expected_trait_ref) + .sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref) .map(|InferOk { mut obligations, .. }| { obligations.extend(nested); obligations @@ -896,7 +895,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .sup(DefineOpaqueTypes::No, target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -995,7 +994,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .sup(DefineOpaqueTypes::No, target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1066,7 +1065,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(b, a) + .eq(DefineOpaqueTypes::No, b, a) .map_err(|_| Unimplemented)?; nested.extend(obligations); } @@ -1114,7 +1113,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_struct) + .eq(DefineOpaqueTypes::No, target, new_struct) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -1144,7 +1143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_tuple) + .eq(DefineOpaqueTypes::No, target, new_tuple) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 38cdaddc1e707..bc1c72da1e175 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,6 +38,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngineExt; @@ -912,7 +913,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .at(&obligation.cause, obligation.param_env) .trace(c1, c2) - .eq(a.substs, b.substs) + .eq(DefineOpaqueTypes::No, a.substs, b.substs) { let mut obligations = new_obligations.obligations; self.add_depth( @@ -930,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Ok(new_obligations) = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) + .eq(DefineOpaqueTypes::No, c1, c2) { let mut obligations = new_obligations.obligations; self.add_depth( @@ -964,8 +965,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) - { + match self.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + c1, + c2, + ) { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, inf_ok.into_obligations(), @@ -993,7 +997,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) { + match self.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + ct.ty(), + ty, + ) { Ok(inf_ok) => self.evaluate_predicates_recursively( previous_stack, inf_ok.into_obligations(), @@ -1751,7 +1759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); self.infcx .at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) + .sup(DefineOpaqueTypes::No, ty::Binder::dummy(placeholder_trait_ref), trait_bound) .map(|InferOk { obligations: _, value: () }| { // This method is called within a probe, so we can't have // inference variables and placeholders escape. @@ -1813,7 +1821,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let is_match = self .infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate, infer_projection) + .sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection) .map_or(false, |InferOk { obligations, value: () }| { self.evaluate_predicates_recursively( TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), @@ -2534,7 +2542,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&cause, obligation.param_env) - .eq(placeholder_obligation_trait_ref, impl_trait_ref) + .eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| { debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx())) })?; @@ -2584,7 +2592,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ) -> Result>, ()> { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) + .sup(DefineOpaqueTypes::No, obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| ()) } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index fcfb60b26030f..8e229dd8d6b98 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,6 +10,7 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; +use rustc_infer::infer::DefineOpaqueTypes; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; @@ -193,7 +194,7 @@ fn fulfill_implication<'tcx>( // do the impls unify? If not, no specialization. let Ok(InferOk { obligations: more_obligations, .. }) = - infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait) + infcx.at(&ObligationCause::dummy(), param_env, ).eq(DefineOpaqueTypes::No,source_trait, target_trait) else { debug!( "fulfill_implication: {:?} does not unify with {:?}", diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bcf63d5a6f628..ab4c36975a0ec 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,15 +1,14 @@ -use rustc_errors::Diagnostic; -use rustc_span::Span; -use smallvec::SmallVec; - +use super::NormalizeExt; +use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Diagnostic; use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferOk; use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, SubstsRef}; +use rustc_span::Span; +use smallvec::SmallVec; -use super::NormalizeExt; -use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; -use rustc_infer::infer::InferOk; pub use rustc_infer::traits::{self, util::*}; /////////////////////////////////////////////////////////////////////////// @@ -201,6 +200,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( ) -> (ImplSubject<'tcx>, impl Iterator>) { let subject = selcx.tcx().bound_impl_subject(impl_def_id); let subject = subject.subst(selcx.tcx(), impl_substs); + let InferOk { value: subject, obligations: normalization_obligations1 } = selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index bcdbbcacc4bcd..3a3bf6a7ab9e8 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,6 +1,6 @@ use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_hir as hir; -use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits; use rustc_middle::ty::ToPredicate; use rustc_span::DUMMY_SP; @@ -47,8 +47,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { // Require the type the impl is implemented on to match // our type, and ignore the impl if there was a mismatch. - let cause = traits::ObligationCause::dummy(); - let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else { + let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, impl_trait_ref.self_ty(), impl_ty) else { continue }; let InferOk { value: (), obligations } = eq_result; From e667872bfdcc48305e1fae90d278693cb089223e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Mar 2023 16:47:14 +0100 Subject: [PATCH 11/14] Update docsfs module documentation --- src/librustdoc/docfs.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index 59393697dfec3..d58b8dc6ad4a4 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -2,7 +2,6 @@ //! //! On Windows this indirects IO into threads to work around performance issues //! with Defender (and other similar virus scanners that do blocking operations). -//! On other platforms this is a thin shim to fs. //! //! Only calls needed to permit this workaround have been abstracted: thus //! fs::read is still done directly via the fs module; if in future rustdoc From e5a5b90afc527dfb87f6034b52b7adca063ca078 Mon Sep 17 00:00:00 2001 From: gimbles <93856041+gimbles@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:55:48 +0530 Subject: [PATCH 12/14] =?UTF-8?q?unequal=20=E2=86=92=20not=20equal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_borrowck/src/dataflow.rs | 2 +- .../rustc_error_codes/src/error_codes/E0416.md | 2 +- compiler/rustc_expand/src/mbe/transcribe.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/consts/int.rs | 14 +++++++------- library/alloc/src/rc.rs | 4 ++-- library/alloc/src/sync.rs | 4 ++-- library/core/src/hash/mod.rs | 2 +- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/primitive_docs.rs | 2 +- library/std/src/primitive_docs.rs | 2 +- library/std/src/sync/remutex.rs | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 0762987e22961..2cbd2e3bc0d86 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -306,7 +306,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given - // pair of array indices are unequal, so that when `places_conflict` returns true, we + // pair of array indices are not equal, so that when `places_conflict` returns true, we // will be assured that two places being compared definitely denotes the same sets of // locations. let definitely_conflicting_borrows = other_borrows_of_local.filter(|&i| { diff --git a/compiler/rustc_error_codes/src/error_codes/E0416.md b/compiler/rustc_error_codes/src/error_codes/E0416.md index 7bc316dafc5fb..8c0edcee52147 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0416.md +++ b/compiler/rustc_error_codes/src/error_codes/E0416.md @@ -23,6 +23,6 @@ Or maybe did you mean to unify? Consider using a guard: # let (A, B, C) = (1, 2, 3); match (A, B, C) { (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } - (y, z, see) => { /* A and B unequal; do another thing */ } + (y, z, see) => { /* A and B not equal; do another thing */ } } ``` diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 47a8b4bc48885..a07cb65170dca 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -367,7 +367,7 @@ impl LockstepIterSize { /// /// Example: `$($($x $y)+*);+` -- we need to make sure that `x` and `y` repeat the same amount as /// each other at the given depth when the macro was invoked. If they don't it might mean they were -/// declared at unequal depths or there was a compile bug. For example, if we have 3 repetitions of +/// declared at depths which weren't equal or there was a compiler bug. For example, if we have 3 repetitions of /// the outer sequence and 4 repetitions of the inner sequence for `x`, we should have the same for /// `y`; otherwise, we can't transcribe them both at the given depth. fn lockstep_iter_size( diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 9312e27df378a..feaed5ea6a5e4 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1081,7 +1081,7 @@ pub enum Rvalue<'tcx> { /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. /// /// For addition, subtraction, and multiplication on integers the error condition is set when - /// the infinite precision result would be unequal to the actual result. + /// the infinite precision result would not be equal to the actual result. /// /// For shift operations on integers the error condition is set when the value of right-hand /// side is greater than or equal to the number of bits in the type of the left-hand side, or diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 75f05c4af23da..2cd791574417a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2215,7 +2215,7 @@ rustc_queries! { } /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being - /// equal to eachother. This might return `Ok` even if the types are unequal, but will never return `Err` if + /// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if /// the types might be equal. query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> { desc { "check whether two const param are definitely not equal to eachother"} diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index eecd78ab6c048..a7f38884ebcc4 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -237,7 +237,7 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to an unsigned integer of the given size. - /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the + /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. #[inline] pub fn try_to_uint(self, size: Size) -> Result { @@ -297,7 +297,7 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to a signed integer of the given size. - /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the + /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. #[inline] pub fn try_to_int(self, size: Size) -> Result { @@ -306,35 +306,35 @@ impl ScalarInt { } /// Tries to convert the `ScalarInt` to i8. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 1 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 1 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i8(self) -> Result { self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i16. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 2 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 2 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i16(self) -> Result { self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i32. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 4 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 4 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i32(self) -> Result { self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i64. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 8 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 8 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i64(self) -> Result { self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to i128. - /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 16 }` + /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 16 }` /// and returns the `ScalarInt`s size in that case. pub fn try_to_i128(self) -> Result { self.try_to_int(Size::from_bits(128)).map(|v| i128::try_from(v).unwrap()) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 77b0447b345ec..089b6b6418dc1 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1738,11 +1738,11 @@ impl PartialEq for Rc { /// Inequality for two `Rc`s. /// - /// Two `Rc`s are unequal if their inner values are unequal. + /// Two `Rc`s are not equal if their inner values are not equal. /// /// If `T` also implements `Eq` (implying reflexivity of equality), /// two `Rc`s that point to the same allocation are - /// never unequal. + /// always equal. /// /// # Examples /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f37573c6f27f4..8a27a7ecdf653 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2475,10 +2475,10 @@ impl PartialEq for Arc { /// Inequality for two `Arc`s. /// - /// Two `Arc`s are unequal if their inner values are unequal. + /// Two `Arc`s are not equal if their inner values are not equal. /// /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same value are never unequal. + /// two `Arc`s that point to the same value are always equal. /// /// # Examples /// diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 71a0d1825efec..3bdde0993b9a2 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -158,7 +158,7 @@ mod sip; /// /// Implementations of `hash` should ensure that the data they /// pass to the `Hasher` are prefix-free. That is, -/// unequal values should cause two different sequences of values to be written, +/// values which are not equal should cause two different sequences of values to be written, /// and neither of the two sequences should be a prefix of the other. /// /// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b8e7d0a68da57..e791158e25948 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3721,7 +3721,7 @@ pub trait Iterator { } } - /// Determines if the elements of this [`Iterator`] are unequal to those of + /// Determines if the elements of this [`Iterator`] are not equal to those of /// another. /// /// # Examples diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 6f78811a186c7..e12a3e378a615 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1110,7 +1110,7 @@ impl Copy for (T,) { /// - [NaN (not a number)](#associatedconstant.NAN): this value results from /// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected /// behavior: -/// - It is unequal to any float, including itself! This is the reason `f32` +/// - It is not equal to any float, including itself! This is the reason `f32` /// doesn't implement the `Eq` trait. /// - It is also neither smaller nor greater than any float, making it /// impossible to sort by the default comparison operation, which is the diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 6f78811a186c7..e12a3e378a615 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1110,7 +1110,7 @@ impl Copy for (T,) { /// - [NaN (not a number)](#associatedconstant.NAN): this value results from /// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected /// behavior: -/// - It is unequal to any float, including itself! This is the reason `f32` +/// - It is not equal to any float, including itself! This is the reason `f32` /// doesn't implement the `Eq` trait. /// - It is also neither smaller nor greater than any float, making it /// impossible to sort by the default comparison operation, which is the diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs index 4c054da64714c..519ec2c32bd5d 100644 --- a/library/std/src/sync/remutex.rs +++ b/library/std/src/sync/remutex.rs @@ -35,7 +35,7 @@ use crate::sys::locks as sys; /// `owner` can be checked by other threads that want to see if they already /// hold the lock, so needs to be atomic. If it compares equal, we're on the /// same thread that holds the mutex and memory access can use relaxed ordering -/// since we're not dealing with multiple threads. If it compares unequal, +/// since we're not dealing with multiple threads. If it's not equal, /// synchronization is left to the mutex, making relaxed memory ordering for /// the `owner` field fine in all cases. pub struct ReentrantMutex { From 683c12cb910f2ee3fbbaf659dafdfef6eb3d6ec5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 15 Mar 2023 11:34:37 -0700 Subject: [PATCH 13/14] rustdoc: remove `std::` from primitive intra-doc link tooltips --- src/librustdoc/html/format.rs | 6 ++++++ tests/rustdoc/intra-doc/prim-methods.rs | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 024ea62c31aa9..27010b771d33b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -771,6 +771,12 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option, cx: &Cont .or_else(|| cache.external_paths.get(&did)) else { return String::new() }; let mut buf = Buffer::new(); + let fqp = if *shortty == ItemType::Primitive { + // primitives are documented in a crate, but not actually part of it + &fqp[fqp.len() - 1..] + } else { + &fqp + }; if let &Some(UrlFragment::Item(id)) = fragment { write!(buf, "{} ", cx.tcx().def_descr(id)); for component in fqp { diff --git a/tests/rustdoc/intra-doc/prim-methods.rs b/tests/rustdoc/intra-doc/prim-methods.rs index a412a23fda835..bc1965aac5594 100644 --- a/tests/rustdoc/intra-doc/prim-methods.rs +++ b/tests/rustdoc/intra-doc/prim-methods.rs @@ -2,6 +2,8 @@ // @has prim_methods/index.html // @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char' +// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html"]/@title' 'primitive char' // @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' +// @has - '//*[@id="main-content"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]/@title' 'method char::len_utf8' //! A [`char`] and its [`char::len_utf8`]. From 3f250a9241a365b606b930d3fcc6b30017243503 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 15 Mar 2023 22:33:10 +0100 Subject: [PATCH 14/14] Mention UEFI target promotion in release notes for 1.67.0 --- RELEASES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 4e974bbe9747e..a26dbbfa4f5ec 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -125,12 +125,13 @@ Compiler - [Optimize field ordering by grouping m\*2^n-sized fields with equivalently aligned ones.](https://github.com/rust-lang/rust/pull/102750/) - [Stabilize native library modifier `verbatim`.](https://github.com/rust-lang/rust/pull/104360/) -Added and removed targets: +Added, updated, and removed targets: - [Add a tier 3 target for PowerPC on AIX](https://github.com/rust-lang/rust/pull/102293/), `powerpc64-ibm-aix`. - [Add a tier 3 target for the Sony PlayStation 1](https://github.com/rust-lang/rust/pull/102689/), `mipsel-sony-psx`. - [Add tier 3 `no_std` targets for the QNX Neutrino RTOS](https://github.com/rust-lang/rust/pull/102701/), `aarch64-unknown-nto-qnx710` and `x86_64-pc-nto-qnx710`. +- [Promote UEFI targets to tier 2](https://github.com/rust-lang/rust/pull/103933/), `aarch64-unknown-uefi`, `i686-unknown-uefi`, and `x86_64-unknown-uefi`. - [Remove tier 3 `linuxkernel` targets](https://github.com/rust-lang/rust/pull/104015/) (not used by the actual kernel). Refer to Rust's [platform support page][platform-support-doc]