From 27893ddac516e7beac952ce0f73127964578d11c Mon Sep 17 00:00:00 2001 From: Bram van den Heuvel Date: Thu, 4 Nov 2021 10:57:42 +0100 Subject: [PATCH 1/8] Group commandline tests in a directory --- .../{ => commandline-argfile}/commandline-argfile-badutf8.args | 0 .../{ => commandline-argfile}/commandline-argfile-badutf8.rs | 2 +- .../commandline-argfile-badutf8.stderr | 0 .../commandline-argfile}/commandline-argfile-missing.rs | 2 +- .../commandline-argfile-missing.stderr | 0 .../{ => commandline-argfile}/commandline-argfile.args | 0 .../rustdoc-ui/{ => commandline-argfile}/commandline-argfile.rs | 2 +- .../ui/{ => command/argfile}/commandline-argfile-badutf8.args | 0 .../ui/{ => command/argfile}/commandline-argfile-badutf8.rs | 2 +- .../ui/{ => command/argfile}/commandline-argfile-badutf8.stderr | 0 .../command/argfile}/commandline-argfile-missing.rs | 2 +- .../ui/{ => command/argfile}/commandline-argfile-missing.stderr | 0 src/test/ui/{ => command/argfile}/commandline-argfile.args | 0 src/test/ui/{ => command/argfile}/commandline-argfile.rs | 2 +- src/test/ui/{ => command}/command-line-diagnostics.rs | 0 src/test/ui/{ => command}/command-line-diagnostics.stderr | 0 16 files changed, 6 insertions(+), 6 deletions(-) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile-badutf8.args (100%) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile-badutf8.rs (87%) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile-badutf8.stderr (100%) rename src/test/{ui => rustdoc-ui/commandline-argfile}/commandline-argfile-missing.rs (92%) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile-missing.stderr (100%) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile.args (100%) rename src/test/rustdoc-ui/{ => commandline-argfile}/commandline-argfile.rs (90%) rename src/test/ui/{ => command/argfile}/commandline-argfile-badutf8.args (100%) rename src/test/ui/{ => command/argfile}/commandline-argfile-badutf8.rs (67%) rename src/test/ui/{ => command/argfile}/commandline-argfile-badutf8.stderr (100%) rename src/test/{rustdoc-ui => ui/command/argfile}/commandline-argfile-missing.rs (79%) rename src/test/ui/{ => command/argfile}/commandline-argfile-missing.stderr (100%) rename src/test/ui/{ => command/argfile}/commandline-argfile.args (100%) rename src/test/ui/{ => command/argfile}/commandline-argfile.rs (70%) rename src/test/ui/{ => command}/command-line-diagnostics.rs (100%) rename src/test/ui/{ => command}/command-line-diagnostics.stderr (100%) diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.args b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.args similarity index 100% rename from src/test/rustdoc-ui/commandline-argfile-badutf8.args rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.args diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.rs b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.rs similarity index 87% rename from src/test/rustdoc-ui/commandline-argfile-badutf8.rs rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.rs index e2984e3ca97ac..19e5dfb619c21 100644 --- a/src/test/rustdoc-ui/commandline-argfile-badutf8.rs +++ b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.rs @@ -1,6 +1,6 @@ // Check to see if we can get parameters from an @argsfile file // -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-badutf8.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.stderr similarity index 100% rename from src/test/rustdoc-ui/commandline-argfile-badutf8.stderr rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile-badutf8.stderr diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-missing.rs similarity index 92% rename from src/test/ui/commandline-argfile-missing.rs rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile-missing.rs index 5a6465bd06469..e48e74cd9eed3 100644 --- a/src/test/ui/commandline-argfile-missing.rs +++ b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-missing.rs @@ -2,7 +2,7 @@ // // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-missing.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.stderr b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile-missing.stderr similarity index 100% rename from src/test/rustdoc-ui/commandline-argfile-missing.stderr rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile-missing.stderr diff --git a/src/test/rustdoc-ui/commandline-argfile.args b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile.args similarity index 100% rename from src/test/rustdoc-ui/commandline-argfile.args rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile.args diff --git a/src/test/rustdoc-ui/commandline-argfile.rs b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile.rs similarity index 90% rename from src/test/rustdoc-ui/commandline-argfile.rs rename to src/test/rustdoc-ui/commandline-argfile/commandline-argfile.rs index cc8c8722c1c35..16184665d9e6d 100644 --- a/src/test/rustdoc-ui/commandline-argfile.rs +++ b/src/test/rustdoc-ui/commandline-argfile/commandline-argfile.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // // check-pass -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/ui/commandline-argfile-badutf8.args b/src/test/ui/command/argfile/commandline-argfile-badutf8.args similarity index 100% rename from src/test/ui/commandline-argfile-badutf8.args rename to src/test/ui/command/argfile/commandline-argfile-badutf8.args diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/command/argfile/commandline-argfile-badutf8.rs similarity index 67% rename from src/test/ui/commandline-argfile-badutf8.rs rename to src/test/ui/command/argfile/commandline-argfile-badutf8.rs index e2984e3ca97ac..0e7407e2e2079 100644 --- a/src/test/ui/commandline-argfile-badutf8.rs +++ b/src/test/ui/command/argfile/commandline-argfile-badutf8.rs @@ -1,6 +1,6 @@ // Check to see if we can get parameters from an @argsfile file // -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args +// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile-badutf8.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/command/argfile/commandline-argfile-badutf8.stderr similarity index 100% rename from src/test/ui/commandline-argfile-badutf8.stderr rename to src/test/ui/command/argfile/commandline-argfile-badutf8.stderr diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.rs b/src/test/ui/command/argfile/commandline-argfile-missing.rs similarity index 79% rename from src/test/rustdoc-ui/commandline-argfile-missing.rs rename to src/test/ui/command/argfile/commandline-argfile-missing.rs index 5a6465bd06469..1cdead6f8e757 100644 --- a/src/test/rustdoc-ui/commandline-argfile-missing.rs +++ b/src/test/ui/command/argfile/commandline-argfile-missing.rs @@ -2,7 +2,7 @@ // // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args +// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile-missing.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/command/argfile/commandline-argfile-missing.stderr similarity index 100% rename from src/test/ui/commandline-argfile-missing.stderr rename to src/test/ui/command/argfile/commandline-argfile-missing.stderr diff --git a/src/test/ui/commandline-argfile.args b/src/test/ui/command/argfile/commandline-argfile.args similarity index 100% rename from src/test/ui/commandline-argfile.args rename to src/test/ui/command/argfile/commandline-argfile.args diff --git a/src/test/ui/commandline-argfile.rs b/src/test/ui/command/argfile/commandline-argfile.rs similarity index 70% rename from src/test/ui/commandline-argfile.rs rename to src/test/ui/command/argfile/commandline-argfile.rs index fc1ba0c8d677d..40b8265cdecc9 100644 --- a/src/test/ui/commandline-argfile.rs +++ b/src/test/ui/command/argfile/commandline-argfile.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // // build-pass -// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args +// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); diff --git a/src/test/ui/command-line-diagnostics.rs b/src/test/ui/command/command-line-diagnostics.rs similarity index 100% rename from src/test/ui/command-line-diagnostics.rs rename to src/test/ui/command/command-line-diagnostics.rs diff --git a/src/test/ui/command-line-diagnostics.stderr b/src/test/ui/command/command-line-diagnostics.stderr similarity index 100% rename from src/test/ui/command-line-diagnostics.stderr rename to src/test/ui/command/command-line-diagnostics.stderr From d4684182096326ccc57ea70bdb080c95607ff238 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Mon, 1 Nov 2021 12:02:01 +0530 Subject: [PATCH 2/8] rustdoc: use Type::def_id() instead of Type::def_id_no_primitives() Signed-off-by: Muhammad Falak R Wani --- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/render/cache.rs | 48 +++++++++++--------- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 7 +-- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 6b9c9a9669b1a..1e951a89023f6 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -303,7 +303,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { desc, parent, parent_idx: None, - search_type: get_index_search_type(&item, self.tcx), + search_type: get_index_search_type(&item, self.tcx, self.cache), aliases: item.attrs.get_doc_aliases(), }); } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index ff1bd5e7ff289..a4a43cba4e69c 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -43,7 +43,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< desc, parent: Some(did), parent_idx: None, - search_type: get_index_search_type(item, tcx), + search_type: get_index_search_type(item, tcx, cache), aliases: item.attrs.get_doc_aliases(), }); } @@ -191,11 +191,12 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< crate fn get_index_search_type<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, + cache: &Cache, ) -> Option { let (mut inputs, mut output) = match *item.kind { - clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx), - clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx), - clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx), + clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx, cache), + clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx, cache), + clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx, cache), _ => return None, }; @@ -249,12 +250,14 @@ crate fn get_real_types<'tcx>( tcx: TyCtxt<'tcx>, recurse: usize, res: &mut Vec, + cache: &Cache, ) { fn insert_ty( res: &mut Vec, tcx: TyCtxt<'_>, ty: Type, mut generics: Vec, + cache: &Cache, ) { let is_full_generic = ty.is_full_generic(); @@ -306,7 +309,7 @@ crate fn get_real_types<'tcx>( // We remove the name of the full generic because we have no use for it. index_ty.name = Some(String::new()); res.push(TypeWithKind::from((index_ty, ItemType::Generic))); - } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { + } else if let Some(kind) = ty.def_id(cache).map(|did| tcx.def_kind(did).into()) { res.push(TypeWithKind::from((index_ty, kind))); } else if ty.is_primitive() { // This is a primitive, let's store it as such. @@ -321,9 +324,7 @@ crate fn get_real_types<'tcx>( if let Type::Generic(arg_s) = *arg { if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => { - ty.def_id_no_primitives() == arg.def_id_no_primitives() - } + WherePredicate::BoundPredicate { ty, .. } => ty.def_id(cache) == arg.def_id(cache), _ => false, }) { let mut ty_generics = Vec::new(); @@ -335,31 +336,38 @@ crate fn get_real_types<'tcx>( continue; } if let Some(ty) = x.get_type() { - get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics); + get_real_types( + generics, + &ty, + tcx, + recurse + 1, + &mut ty_generics, + cache, + ); } } } } - insert_ty(res, tcx, arg.clone(), ty_generics); + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { let mut ty_generics = Vec::new(); for bound in bound.get_bounds().unwrap_or(&[]) { if let Some(path) = bound.get_trait_path() { let ty = Type::ResolvedPath { did: path.def_id(), path }; - get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics); + get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache); } } - insert_ty(res, tcx, arg.clone(), ty_generics); + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } } else { let mut ty_generics = Vec::new(); if let Some(arg_generics) = arg.generics() { for gen in arg_generics.iter() { - get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics); + get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics, cache); } } - insert_ty(res, tcx, arg.clone(), ty_generics); + insert_ty(res, tcx, arg.clone(), ty_generics, cache); } } @@ -371,6 +379,7 @@ crate fn get_all_types<'tcx>( generics: &Generics, decl: &FnDecl, tcx: TyCtxt<'tcx>, + cache: &Cache, ) -> (Vec, Vec) { let mut all_types = Vec::new(); for arg in decl.inputs.values.iter() { @@ -380,14 +389,13 @@ crate fn get_all_types<'tcx>( // FIXME: performance wise, it'd be much better to move `args` declaration outside of the // loop and replace this line with `args.clear()`. let mut args = Vec::new(); - get_real_types(generics, &arg.type_, tcx, 0, &mut args); + get_real_types(generics, &arg.type_, tcx, 0, &mut args, cache); if !args.is_empty() { // FIXME: once back to performance improvements, replace this line with: // `all_types.extend(args.drain(..));`. all_types.extend(args); } else { - if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) - { + if let Some(kind) = arg.type_.def_id(cache).map(|did| tcx.def_kind(did).into()) { all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind))); } } @@ -396,11 +404,9 @@ crate fn get_all_types<'tcx>( let mut ret_types = Vec::new(); match decl.output { FnRetTy::Return(ref return_type) => { - get_real_types(generics, return_type, tcx, 0, &mut ret_types); + get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache); if ret_types.is_empty() { - if let Some(kind) = - return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) - { + if let Some(kind) = return_type.def_id(cache).map(|did| tcx.def_kind(did).into()) { ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind))); } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 25fef114d95fd..fdc552872ca73 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2166,7 +2166,7 @@ fn sidebar_deref_methods( } // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id_no_primitives() { + if let Some(target_did) = target.def_id(c) { if let Some(target_impls) = c.impls.get(&target_did) { if let Some(target_deref_impl) = target_impls.iter().find(|i| { i.inner_impl() diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 77513b05ff2f9..2aaf1dabd8696 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -57,6 +57,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate // Follow all `Deref` targets of included items and recursively add them as valid fn add_deref_target( + cx: &DocContext<'_>, map: &FxHashMap, cleaner: &mut BadImplStripper, type_did: DefId, @@ -65,14 +66,14 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate debug!("add_deref_target: type {:?}, target {:?}", type_did, target); if let Some(target_prim) = target.primitive_type() { cleaner.prims.insert(target_prim); - } else if let Some(target_did) = target.def_id_no_primitives() { + } else if let Some(target_did) = target.def_id(&cx.cache) { // `impl Deref for S` if target_did == type_did { // Avoid infinite cycles return; } cleaner.items.insert(target_did.into()); - add_deref_target(map, cleaner, target_did); + add_deref_target(cx, map, cleaner, target_did); } } } @@ -102,7 +103,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate // `Deref` target type and the impl for type positions, this map of types is keyed by // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. if cleaner.keep_impl_with_def_id(for_did.into()) { - add_deref_target(&type_did_to_deref_target, &mut cleaner, for_did); + add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did); } } } From fc9624c6738c57f32e6811ed93b3085415e61ccd Mon Sep 17 00:00:00 2001 From: Jimmy Envall Date: Wed, 10 Nov 2021 18:49:30 +0100 Subject: [PATCH 3/8] Fix trait object error code --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- src/test/ui/editions/dyn-trait-sugg-2021.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 93b2a59525972..aae59eee99142 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -952,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = rustc_errors::struct_span_err!( self.sess(), self_ty.span, - E0783, + E0782, "{}", msg, ); diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.stderr b/src/test/ui/editions/dyn-trait-sugg-2021.stderr index f6e9fa96a15b5..a7119b073abfa 100644 --- a/src/test/ui/editions/dyn-trait-sugg-2021.stderr +++ b/src/test/ui/editions/dyn-trait-sugg-2021.stderr @@ -1,4 +1,4 @@ -error[E0783]: trait objects without an explicit `dyn` are deprecated +error[E0782]: trait objects without an explicit `dyn` are deprecated --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); @@ -6,4 +6,4 @@ LL | Foo::hi(123); error: aborting due to previous error -For more information about this error, try `rustc --explain E0783`. +For more information about this error, try `rustc --explain E0782`. From 5cfc7ce3372852b76dce6e6354faa3e7f0bf8598 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Thu, 11 Nov 2021 12:00:02 +0530 Subject: [PATCH 4/8] librustdoc: revert use of def_id for one of the edge case Signed-off-by: Muhammad Falak R Wani --- src/librustdoc/html/render/cache.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index a4a43cba4e69c..1dda80ff38c58 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -257,7 +257,7 @@ crate fn get_real_types<'tcx>( tcx: TyCtxt<'_>, ty: Type, mut generics: Vec, - cache: &Cache, + _cache: &Cache, ) { let is_full_generic = ty.is_full_generic(); @@ -309,7 +309,7 @@ crate fn get_real_types<'tcx>( // We remove the name of the full generic because we have no use for it. index_ty.name = Some(String::new()); res.push(TypeWithKind::from((index_ty, ItemType::Generic))); - } else if let Some(kind) = ty.def_id(cache).map(|did| tcx.def_kind(did).into()) { + } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { res.push(TypeWithKind::from((index_ty, kind))); } else if ty.is_primitive() { // This is a primitive, let's store it as such. @@ -324,7 +324,9 @@ crate fn get_real_types<'tcx>( if let Type::Generic(arg_s) = *arg { if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => ty.def_id(cache) == arg.def_id(cache), + WherePredicate::BoundPredicate { ty, .. } => { + ty.def_id_no_primitives() == arg.def_id_no_primitives() + } _ => false, }) { let mut ty_generics = Vec::new(); @@ -395,7 +397,8 @@ crate fn get_all_types<'tcx>( // `all_types.extend(args.drain(..));`. all_types.extend(args); } else { - if let Some(kind) = arg.type_.def_id(cache).map(|did| tcx.def_kind(did).into()) { + if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) + { all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind))); } } @@ -406,7 +409,9 @@ crate fn get_all_types<'tcx>( FnRetTy::Return(ref return_type) => { get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache); if ret_types.is_empty() { - if let Some(kind) = return_type.def_id(cache).map(|did| tcx.def_kind(did).into()) { + if let Some(kind) = + return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) + { ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind))); } } From 26ca71fdb2070ae970ea9ce40a52a7b663897940 Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 9 Nov 2021 20:21:51 +0100 Subject: [PATCH 5/8] normalize argument b in equate_normalized_inputs_output --- .../src/type_check/input_output.rs | 60 ++++++++++++------- compiler/rustc_borrowck/src/type_check/mod.rs | 5 +- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 24332690bec31..92d2d04f23f23 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,13 +7,16 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use crate::type_check::constraint_conversion::ConstraintConversion; use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; -use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::Ty; use rustc_span::Span; -use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; +use rustc_trait_selection::traits::query::Fallible; +use type_op::TypeOpOutput; use crate::universal_regions::UniversalRegions; @@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let (&normalized_output_ty, normalized_input_tys) = normalized_inputs_and_output.split_last().unwrap(); + debug!(?normalized_output_ty); + debug!(?normalized_input_tys); + let mir_def_id = body.source.def_id().expect_local(); // If the user explicitly annotated the input types, extract @@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); break; } + // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; + let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( normalized_input_ty, @@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // If the user explicitly annotated the input types, enforce those. let user_provided_input_ty = self.normalize(user_provided_input_ty, Locations::All(mir_input_span)); + self.equate_normalized_input_or_output( user_provided_input_ty, mir_input_ty, @@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd // like to normalize *before* inserting into `local_decls`, but // doing so ends up causing some other trouble. - let b = match self - .infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .normalize(b) - { - Ok(n) => { - debug!("equate_inputs_and_outputs: {:?}", n); - if n.obligations.iter().all(|o| { - matches!( - o.predicate.kind().skip_binder(), - ty::PredicateKind::RegionOutlives(_) - | ty::PredicateKind::TypeOutlives(_) - ) - }) { - n.value - } else { - b - } - } + let b = match self.normalize_and_add_constraints(b) { + Ok(n) => n, Err(_) => { debug!("equate_inputs_and_outputs: NoSolution"); b } }; + // Note: if we have to introduce new placeholders during normalization above, then we won't have // added those universes to the universe info, which we would want in `relate_tys`. if let Err(terr) = @@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } + + pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible> { + let TypeOpOutput { output: norm_ty, constraints, .. } = + self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?; + + debug!("{:?} normalized to {:?}", t, norm_ty); + + for data in constraints.into_iter().collect::>() { + ConstraintConversion::new( + self.infcx, + &self.borrowck_context.universal_regions, + &self.region_bound_pairs, + Some(self.implicit_region_bound), + self.param_env, + Locations::All(DUMMY_SP), + ConstraintCategory::Internal, + &mut self.borrowck_context.constraints, + ) + .convert_all(&*data); + } + + Ok(norm_ty) + } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ddd077c22faf8..da26d9c7b8779 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> { } struct BorrowCheckContext<'a, 'tcx> { - universal_regions: &'a UniversalRegions<'tcx>, + pub(crate) universal_regions: &'a UniversalRegions<'tcx>, location_table: &'a LocationTable, all_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, - constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, upvars: &'a [Upvar<'tcx>], } @@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category) } + #[instrument(skip(self, category), level = "debug")] fn eq_types( &mut self, expected: Ty<'tcx>, From 6b3695d480cfb6f61f59df1184239e16dc1c6795 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 12 Nov 2021 15:25:13 +0100 Subject: [PATCH 6/8] Remove unneeded FIXME: after testing the suggested changes, we reached the conclusion that the code readibility wasn't worth the almost unnoticeable perf improvement --- src/librustdoc/html/render/cache.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index ff1bd5e7ff289..e2b7b21473996 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -377,13 +377,9 @@ crate fn get_all_types<'tcx>( if arg.type_.is_self_type() { continue; } - // FIXME: performance wise, it'd be much better to move `args` declaration outside of the - // loop and replace this line with `args.clear()`. let mut args = Vec::new(); get_real_types(generics, &arg.type_, tcx, 0, &mut args); if !args.is_empty() { - // FIXME: once back to performance improvements, replace this line with: - // `all_types.extend(args.drain(..));`. all_types.extend(args); } else { if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) From 7a4aa65810b1e77f5bbfa442ca36b6fd9530e4be Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 9 Nov 2021 20:41:13 +0100 Subject: [PATCH 7/8] add tests --- .../normalize-under-binder/issue-90612.rs | 43 +++++++++++++++++++ .../normalize-under-binder/issue-90638.rs | 37 ++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs new file mode 100644 index 0000000000000..e150ecfe9a0dc --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(generic_associated_types)] + +use std::marker::PhantomData; + +trait Family: Sized { + type Item<'a>; + + fn apply_all(&self, f: F) + where + F: FamilyItemFn { } +} + +struct Array(PhantomData); + +impl Family for Array { + type Item<'a> = &'a T; +} + +trait FamilyItemFn { + fn apply(&self, item: T::Item<'_>); +} + +impl FamilyItemFn for F +where + T: Family, + for<'a> F: Fn(T::Item<'a>) +{ + fn apply(&self, item: T::Item<'_>) { + (*self)(item); + } +} + +fn process(array: Array) { + // Works + array.apply_all(|x: &T| { }); + + // ICE: NoSolution + array.apply_all(|x: as Family>::Item<'_>| { }); +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs new file mode 100644 index 0000000000000..18b7f383482a1 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs @@ -0,0 +1,37 @@ +//check-pass + +#![feature(generic_associated_types)] + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + +trait IsCovariant<'a> {} + +struct Yoke Yokeable<'a>> { + data: Y, +} + +impl Yokeable<'a>> Yoke { + fn project Yokeable<'a>>(&self, _f: for<'a> fn(>::Output, &'a ()) + -> >::Output) -> Yoke { + + unimplemented!() + } +} + +fn _upcast(x: Yoke) -> Yoke + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> >::Output: IsCovariant<'a> + { + x.project(|data, _| { + Box::new(data) + }) +} + + +impl<'a> Yokeable<'a> for Box + 'static> { + type Output = Box + 'a>; +} + +fn main() {} From 688ed0a019af8ac5097ac829ef24e4c69cd8d5c8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 12 Nov 2021 22:25:31 -0700 Subject: [PATCH 8/8] Use an empty Vec instead of Option --- src/librustdoc/html/render/cache.rs | 1 - src/librustdoc/html/render/mod.rs | 19 +++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 7aa950d905de1..6f90695067c78 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -204,7 +204,6 @@ crate fn get_index_search_type<'tcx>( inputs.retain(|a| a.ty.name.is_some()); output.retain(|a| a.ty.name.is_some()); - let output = if output.is_empty() { None } else { Some(output) }; Some(IndexItemFunctionType { inputs, output }) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fdadc68998dc6..00e8af22b4830 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -117,7 +117,7 @@ crate struct RenderType { #[derive(Debug)] crate struct IndexItemFunctionType { inputs: Vec, - output: Option>, + output: Vec, } impl Serialize for IndexItemFunctionType { @@ -126,21 +126,16 @@ impl Serialize for IndexItemFunctionType { S: Serializer, { // If we couldn't figure out a type, just write `null`. - let mut iter = self.inputs.iter(); - if match self.output { - Some(ref output) => iter.chain(output.iter()).any(|i| i.ty.name.is_none()), - None => iter.any(|i| i.ty.name.is_none()), - } { + let has_missing = self.inputs.iter().chain(self.output.iter()).any(|i| i.ty.name.is_none()); + if has_missing { serializer.serialize_none() } else { let mut seq = serializer.serialize_seq(None)?; seq.serialize_element(&self.inputs)?; - if let Some(output) = &self.output { - if output.len() > 1 { - seq.serialize_element(&output)?; - } else { - seq.serialize_element(&output[0])?; - } + match self.output.as_slice() { + [] => {} + [one] => seq.serialize_element(one)?, + all => seq.serialize_element(all)?, } seq.end() }