From b498870d9c992e61e0f7930f2679b091b5f2ddbc Mon Sep 17 00:00:00 2001 From: Roxane Date: Wed, 2 Dec 2020 22:25:22 -0500 Subject: use hir::Place instead of Symbol in closure_kind_origin --- .../closure-origin-multi-variant-diagnostics.rs | 31 ++++++++++++++++++ ...closure-origin-multi-variant-diagnostics.stderr | 26 +++++++++++++++ .../closure-origin-single-variant-diagnostics.rs | 26 +++++++++++++++ ...losure-origin-single-variant-diagnostics.stderr | 37 ++++++++++++++++++++++ .../closure-origin-struct-diagnostics.rs | 25 +++++++++++++++ .../closure-origin-struct-diagnostics.stderr | 26 +++++++++++++++ .../closure-origin-tuple-diagnostics-1.rs | 16 ++++++++++ .../closure-origin-tuple-diagnostics-1.stderr | 26 +++++++++++++++ .../closure-origin-tuple-diagnostics.rs | 15 +++++++++ .../closure-origin-tuple-diagnostics.stderr | 23 ++++++++++++++ 10 files changed, 251 insertions(+) create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr (limited to 'src') diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs new file mode 100644 index 00000000000..2916d8c794f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs @@ -0,0 +1,31 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| `#[warn(incomplete_features)]` on by default +//~| see issue #53488 + +// Check that precise paths are being reported back in the error message. + + +enum MultiVariant { + Point(i32, i32), + Meta(i32) +} + +fn main() { + let mut point = MultiVariant::Point(10, -10,); + + let mut meta = MultiVariant::Meta(1); + + let c = || { + if let MultiVariant::Point(ref mut x, _) = point { + *x += 1; + } + + if let MultiVariant::Meta(ref mut v) = meta { + *v += 1; + } + }; + + let a = c; + let b = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr new file mode 100644 index 00000000000..de0bfe3bd76 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -0,0 +1,26 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13 + | +LL | let a = c; + | - value moved here +LL | let b = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52 + | +LL | if let MultiVariant::Point(ref mut x, _) = point { + | ^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs new file mode 100644 index 00000000000..8486f03f2eb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs @@ -0,0 +1,26 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| `#[warn(incomplete_features)]` on by default +//~| see issue #53488 + +// Check that precise paths are being reported back in the error message. + +enum SingleVariant { + Point(i32, i32), +} + +fn main() { + let mut point = SingleVariant::Point(10, -10); + + let c = || { + // FIXME(project-rfc-2229#24): Change this to be a destructure pattern + // once this is fixed, to remove the warning. + if let SingleVariant::Point(ref mut x, _) = point { + //~^ WARNING: irrefutable if-let pattern + *x += 1; + } + }; + + let b = c; + let a = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr new file mode 100644 index 00000000000..ad66f6d7ffc --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -0,0 +1,37 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +warning: irrefutable if-let pattern + --> $DIR/closure-origin-single-variant-diagnostics.rs:18:9 + | +LL | / if let SingleVariant::Point(ref mut x, _) = point { +LL | | +LL | | *x += 1; +LL | | } + | |_________^ + | + = note: `#[warn(irrefutable_let_patterns)]` on by default + +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-single-variant-diagnostics.rs:25:13 + | +LL | let b = c; + | - value moved here +LL | let a = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-single-variant-diagnostics.rs:18:53 + | +LL | if let SingleVariant::Point(ref mut x, _) = point { + | ^^^^^ + +error: aborting due to previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs new file mode 100644 index 00000000000..103890f1f35 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs @@ -0,0 +1,25 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| `#[warn(incomplete_features)]` on by default +//~| see issue #53488 + +// Check that precise paths are being reported back in the error message. + +struct Y { + y: X +} + +struct X { + a: u32, + b: u32, +} + +fn main() { + let mut x = Y { y: X { a: 5, b: 0 } }; + let hello = || { + x.y.a += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr new file mode 100644 index 00000000000..474d77b7cd2 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -0,0 +1,26 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closure-origin-struct-diagnostics.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-struct-diagnostics.rs:24:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment + --> $DIR/closure-origin-struct-diagnostics.rs:20:9 + | +LL | x.y.a += 1; + | ^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs new file mode 100644 index 00000000000..6b078d2329c --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs @@ -0,0 +1,16 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| `#[warn(incomplete_features)]` on by default +//~| see issue #53488 + +// Check that precise paths are being reported back in the error message. + +fn main() { + let mut x = (5, 0); + let hello = || { + x.0 += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr new file mode 100644 index 00000000000..716728e96ec --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -0,0 +1,26 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment + --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9 + | +LL | x.0 += 1; + | ^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs new file mode 100644 index 00000000000..0638db60769 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs @@ -0,0 +1,15 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +//~| `#[warn(incomplete_features)]` on by default +//~| see issue #53488 +struct S(String, String); + +fn expect_fn(_f: F) {} + +fn main() { + let s = S(format!("s"), format!("s")); + let c = || { //~ ERROR expected a closure that implements the `Fn` + let s = s.1; + }; + expect_fn(c); +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr new file mode 100644 index 00000000000..77eb2a94ffb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -0,0 +1,23 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closure-origin-tuple-diagnostics.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-tuple-diagnostics.rs:11:13 + | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let s = s.1; + | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment +LL | }; +LL | expect_fn(c); + | --------- the requirement to implement `Fn` derives from here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0525`. -- cgit 1.4.1-3-g733a5 From b7071b2353199cd438f15dd3068a9d64d3fab93c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 6 Jan 2021 23:50:02 +0300 Subject: resolve: Simplify collection of traits in scope --- compiler/rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/late.rs | 72 ++---------- compiler/rustc_resolve/src/lib.rs | 127 +++++++++++----------- src/librustdoc/passes/collect_intra_doc_links.rs | 9 +- src/test/ui/hygiene/traits-in-scope.rs | 53 +++++++++ src/test/ui/underscore-imports/hygiene.rs | 10 +- src/test/ui/underscore-imports/hygiene.stderr | 27 ----- 7 files changed, 139 insertions(+), 161 deletions(-) create mode 100644 src/test/ui/hygiene/traits-in-scope.rs delete mode 100644 src/test/ui/underscore-imports/hygiene.stderr (limited to 'src') diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e96fc185b7e..4ab14c158d3 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -115,7 +115,7 @@ impl<'a> Resolver<'a> { self.get_module(parent_id) } - crate fn get_module(&mut self, def_id: DefId) -> Module<'a> { + pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { // If this is a local module, it will be in `module_map`, no need to recalculate it. if let Some(def_id) = def_id.as_local() { return self.module_map[&def_id]; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8544e1d8ee5..025bb24dfe8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -14,7 +14,6 @@ use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::*; -use rustc_ast::{unwrap_or, walk_list}; use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; @@ -1911,7 +1910,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // it needs to be added to the trait map. if ns == ValueNS { let item_name = path.last().unwrap().ident; - let traits = self.get_traits_containing_item(item_name, ns); + let traits = self.traits_in_scope(item_name, ns); self.r.trait_map.insert(id, traits); } @@ -2372,12 +2371,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // field, we need to add any trait methods we find that match // the field name so that we can do some nice error reporting // later on in typeck. - let traits = self.get_traits_containing_item(ident, ValueNS); + let traits = self.traits_in_scope(ident, ValueNS); self.r.trait_map.insert(expr.id, traits); } ExprKind::MethodCall(ref segment, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.get_traits_containing_item(segment.ident, ValueNS); + let traits = self.traits_in_scope(segment.ident, ValueNS); self.r.trait_map.insert(expr.id, traits); } _ => { @@ -2386,64 +2385,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - fn get_traits_containing_item( - &mut self, - mut ident: Ident, - ns: Namespace, - ) -> Vec { - debug!("(getting traits containing item) looking for '{}'", ident.name); - - let mut found_traits = Vec::new(); - // Look for the current trait. - if let Some((module, _)) = self.current_trait_ref { - if self - .r - .resolve_ident_in_module( - ModuleOrUniformRoot::Module(module), - ident, - ns, - &self.parent_scope, - false, - module.span, - ) - .is_ok() - { - let def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); - } - } - - ident.span = ident.span.normalize_to_macros_2_0(); - let mut search_module = self.parent_scope.module; - loop { - self.r.get_traits_in_module_containing_item( - ident, - ns, - search_module, - &mut found_traits, - &self.parent_scope, - ); - let mut span_data = ident.span.data(); - search_module = unwrap_or!( - self.r.hygienic_lexical_parent(search_module, &mut span_data.ctxt), - break - ); - ident.span = span_data.span(); - } - - if let Some(prelude) = self.r.prelude { - if !search_module.no_implicit_prelude { - self.r.get_traits_in_module_containing_item( - ident, - ns, - prelude, - &mut found_traits, - &self.parent_scope, - ); - } - } - - found_traits + fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec { + self.r.traits_in_scope( + self.current_trait_ref.as_ref().map(|(module, _)| *module), + &self.parent_scope, + ident.span.ctxt(), + Some((ident.name, ns)), + ) } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 86bb1c77911..fa2b9b823a7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -44,9 +44,9 @@ use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; +use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, ResolverOutputs}; -use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -1477,49 +1477,76 @@ impl<'a> Resolver<'a> { self.crate_loader.postprocess(krate); } - fn get_traits_in_module_containing_item( + pub fn traits_in_scope( + &mut self, + current_trait: Option>, + parent_scope: &ParentScope<'a>, + ctxt: SyntaxContext, + assoc_item: Option<(Symbol, Namespace)>, + ) -> Vec { + let mut found_traits = Vec::new(); + + if let Some(module) = current_trait { + if self.trait_may_have_item(Some(module), assoc_item) { + let def_id = module.def_id().unwrap(); + found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); + } + } + + self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| { + match scope { + Scope::Module(module) => { + this.traits_in_module(module, assoc_item, &mut found_traits); + } + Scope::StdLibPrelude => { + if let Some(module) = this.prelude { + this.traits_in_module(module, assoc_item, &mut found_traits); + } + } + Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {} + _ => unreachable!(), + } + None::<()> + }); + + found_traits + } + + fn traits_in_module( &mut self, - ident: Ident, - ns: Namespace, module: Module<'a>, + assoc_item: Option<(Symbol, Namespace)>, found_traits: &mut Vec, - parent_scope: &ParentScope<'a>, ) { - assert!(ns == TypeNS || ns == ValueNS); module.ensure_traits(self); let traits = module.traits.borrow(); + for (trait_name, trait_binding) in traits.as_ref().unwrap().iter() { + if self.trait_may_have_item(trait_binding.module(), assoc_item) { + let def_id = trait_binding.res().def_id(); + let import_ids = self.find_transitive_imports(&trait_binding.kind, *trait_name); + found_traits.push(TraitCandidate { def_id, import_ids }); + } + } + } - for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - // Traits have pseudo-modules that can be used to search for the given ident. - if let Some(module) = binding.module() { - let mut ident = ident; - if ident.span.glob_adjust(module.expansion, binding.span).is_none() { - continue; - } - if self - .resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - parent_scope, - false, - module.span, - ) - .is_ok() - { - let import_ids = self.find_transitive_imports(&binding.kind, trait_name); - let trait_def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } - } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { - // For now, just treat all trait aliases as possible candidates, since we don't - // know if the ident is somewhere in the transitive bounds. - let import_ids = self.find_transitive_imports(&binding.kind, trait_name); - let trait_def_id = binding.res().def_id(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } else { - bug!("candidate is not trait or trait alias?") + // List of traits in scope is pruned on best effort basis. We reject traits not having an + // associated item with the given name and namespace (if specified). This is a conservative + // optimization, proper hygienic type-based resolution of associated items is done in typeck. + // We don't reject trait aliases (`trait_module == None`) because we don't have access to their + // associated items. + fn trait_may_have_item( + &mut self, + trait_module: Option>, + assoc_item: Option<(Symbol, Namespace)>, + ) -> bool { + match (trait_module, assoc_item) { + (Some(trait_module), Some((name, ns))) => { + self.resolutions(trait_module).borrow().iter().any(|resolution| { + let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution; + assoc_ns == ns && assoc_ident.name == name + }) } + _ => true, } } @@ -3227,34 +3254,6 @@ impl<'a> Resolver<'a> { }) } - /// This is equivalent to `get_traits_in_module_containing_item`, but without filtering by the associated item. - /// - /// This is used by rustdoc for intra-doc links. - pub fn traits_in_scope(&mut self, module_id: DefId) -> Vec { - let module = self.get_module(module_id); - module.ensure_traits(self); - let traits = module.traits.borrow(); - let to_candidate = - |this: &mut Self, &(trait_name, binding): &(Ident, &NameBinding<'_>)| TraitCandidate { - def_id: binding.res().def_id(), - import_ids: this.find_transitive_imports(&binding.kind, trait_name), - }; - - let mut candidates: Vec<_> = - traits.as_ref().unwrap().iter().map(|x| to_candidate(self, x)).collect(); - - if let Some(prelude) = self.prelude { - if !module.no_implicit_prelude { - prelude.ensure_traits(self); - candidates.extend( - prelude.traits.borrow().as_ref().unwrap().iter().map(|x| to_candidate(self, x)), - ); - } - } - - candidates - } - /// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>` /// isn't something that can be returned because it can't be made to live that long, /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9cba1b7b0f1..4b5eb4850a3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -19,7 +19,7 @@ use rustc_session::lint::{ builtin::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}, Lint, }; -use rustc_span::hygiene::MacroKind; +use rustc_span::hygiene::{MacroKind, SyntaxContext}; use rustc_span::symbol::Ident; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; @@ -770,7 +770,12 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx let mut cache = cx.module_trait_cache.borrow_mut(); let in_scope_traits = cache.entry(module).or_insert_with(|| { cx.enter_resolver(|resolver| { - resolver.traits_in_scope(module).into_iter().map(|candidate| candidate.def_id).collect() + let parent_scope = &ParentScope::module(resolver.get_module(module), resolver); + resolver + .traits_in_scope(None, parent_scope, SyntaxContext::root(), None) + .into_iter() + .map(|candidate| candidate.def_id) + .collect() }) }); diff --git a/src/test/ui/hygiene/traits-in-scope.rs b/src/test/ui/hygiene/traits-in-scope.rs new file mode 100644 index 00000000000..548bb226b71 --- /dev/null +++ b/src/test/ui/hygiene/traits-in-scope.rs @@ -0,0 +1,53 @@ +// Macros with def-site hygiene still bring traits into scope. +// It is not clear whether this is desirable behavior or not. +// It is also not clear how to prevent it if it is not desirable. + +// check-pass + +#![feature(decl_macro)] +#![feature(trait_alias)] + +mod traits { + pub trait Trait1 { + fn simple_import(&self) {} + } + pub trait Trait2 { + fn renamed_import(&self) {} + } + pub trait Trait3 { + fn underscore_import(&self) {} + } + pub trait Trait4 { + fn trait_alias(&self) {} + } + + impl Trait1 for () {} + impl Trait2 for () {} + impl Trait3 for () {} + impl Trait4 for () {} +} + +macro m1() { + use traits::Trait1; +} +macro m2() { + use traits::Trait2 as Alias; +} +macro m3() { + use traits::Trait3 as _; +} +macro m4() { + trait Alias = traits::Trait4; +} + +fn main() { + m1!(); + m2!(); + m3!(); + m4!(); + + ().simple_import(); + ().renamed_import(); + ().underscore_import(); + ().trait_alias(); +} diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs index a254f6eaa59..c4db6524538 100644 --- a/src/test/ui/underscore-imports/hygiene.rs +++ b/src/test/ui/underscore-imports/hygiene.rs @@ -1,5 +1,6 @@ -// Make sure that underscore imports have the same hygiene considerations as -// other imports. +// Make sure that underscore imports have the same hygiene considerations as other imports. + +// check-pass #![feature(decl_macro)] @@ -7,7 +8,6 @@ mod x { pub use std::ops::Deref as _; } - macro glob_import() { pub use crate::x::*; } @@ -35,6 +35,6 @@ fn main() { use crate::z::*; glob_import!(); underscore_import!(); - (&()).deref(); //~ ERROR no method named `deref` - (&mut ()).deref_mut(); //~ ERROR no method named `deref_mut` + (&()).deref(); + (&mut ()).deref_mut(); } diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr deleted file mode 100644 index 29836137860..00000000000 --- a/src/test/ui/underscore-imports/hygiene.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0599]: no method named `deref` found for reference `&()` in the current scope - --> $DIR/hygiene.rs:38:11 - | -LL | (&()).deref(); - | ^^^^^ method not found in `&()` - | - = help: items from traits can only be used if the trait is in scope -help: the following trait is implemented but not in scope; perhaps add a `use` for it: - | -LL | use std::ops::Deref; - | - -error[E0599]: no method named `deref_mut` found for mutable reference `&mut ()` in the current scope - --> $DIR/hygiene.rs:39:15 - | -LL | (&mut ()).deref_mut(); - | ^^^^^^^^^ method not found in `&mut ()` - | - = help: items from traits can only be used if the trait is in scope -help: the following trait is implemented but not in scope; perhaps add a `use` for it: - | -LL | use std::ops::DerefMut; - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0599`. -- cgit 1.4.1-3-g733a5 From 67660704229ba03d9b305bd938cd1f8f0bf65d11 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 11 Jan 2021 20:28:17 -0500 Subject: Allow downloading LLVM on Windows - Don't ignore packaging `llvm/lib/` for `rust-dev` when LLVM is linked statically - Add `link-type.txt` so bootstrap knows whether llvm was linked statically or dynamically - Don't assume CI LLVM is linked dynamically in `bootstrap::config` - Fall back to dynamic linking if `link-type.txt` doesn't exist - Fix existing bug that split the output of `llvm-config` on lines, not spaces - Enable building LLVM tests This works around the following llvm bug: ``` llvm-config: error: component libraries and shared library llvm-config: error: missing: /home/joshua/rustc2/build/x86_64-unknown-linux-gnu/llvm/build/lib/libgtest.a llvm-config: error: missing: /home/joshua/rustc2/build/x86_64-unknown-linux-gnu/llvm/build/lib/libgtest_main.a llvm-config: error: missing: /home/joshua/rustc2/build/x86_64-unknown-linux-gnu/llvm/build/lib/libLLVMTestingSupport.a thread 'main' panicked at 'command did not execute successfully: "/home/joshua/rustc2/build/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-config" "--libfiles" ``` I'm not sure why llvm-config thinks these are required, but to avoid the error, this builds them anyway. - Temporarily set windows as the try builder. This should be reverted before merging. - Bump version of `download-ci-llvm-stamp` `src/llvm-project` hasn't changed, but the generated tarball has. - Only special case MacOS when dynamic linking. Static linking works fine. - Store `link-type.txt` to the top-level of the tarball This allows writing the link type unconditionally. Previously, bootstrap had to keep track of whether the file IO *would* succeed (it would fail if `lib/` didn't exist), which was prone to bugs. - Make `link-type.txt` required Anyone downloading this from CI should be using a version of bootstrap that matches the version of the uploaded artifacts. So a missing link-type indicates a bug in x.py. --- src/bootstrap/config.rs | 6 +++-- src/bootstrap/dist.rs | 48 ++++++++++++++++++++++-------------- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/native.rs | 1 - 4 files changed, 35 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index f4d89a89c14..ad937f79254 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -816,8 +816,10 @@ impl Config { check_ci_llvm!(llvm.allow_old_toolchain); check_ci_llvm!(llvm.polly); - // CI-built LLVM is shared - config.llvm_link_shared = true; + // CI-built LLVM can be either dynamic or static. + let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm"); + let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt"))); + config.llvm_link_shared = link_type == "dynamic"; } if config.llvm_thin_lto { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e2c2e19b0bc..af9c0fb04bc 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1800,19 +1800,11 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { } } -/// Maybe add libLLVM.so to the given destination lib-dir. It will only have -/// been built if LLVM tools are linked dynamically. +/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking. /// -/// Note: This function does not yet support Windows, but we also don't support -/// linking LLVM tools dynamically on Windows yet. -fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) { - if !builder.config.llvm_link_shared { - // We do not need to copy LLVM files into the sysroot if it is not - // dynamically linked; it is already included into librustc_llvm - // statically. - return; - } +/// Returns whether the files were actually copied. +fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool { if let Some(config) = builder.config.target_config.get(&target) { if config.llvm_config.is_some() && !builder.config.llvm_from_ci { // If the LLVM was externally provided, then we don't currently copy @@ -1828,7 +1820,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir // // If the LLVM is coming from ourselves (just from CI) though, we // still want to install it, as it otherwise won't be available. - return; + return false; } } @@ -1837,31 +1829,48 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir // clear why this is the case, though. llvm-config will emit the versioned // paths and we don't want those in the sysroot (as we're expecting // unversioned paths). - if target.contains("apple-darwin") { + if target.contains("apple-darwin") && builder.config.llvm_link_shared { let src_libdir = builder.llvm_out(target).join("lib"); let llvm_dylib_path = src_libdir.join("libLLVM.dylib"); if llvm_dylib_path.exists() { builder.install(&llvm_dylib_path, dst_libdir, 0o644); } + !builder.config.dry_run } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) { - let files = output(Command::new(llvm_config).arg("--libfiles")); - for file in files.lines() { + let mut cmd = Command::new(llvm_config); + cmd.arg("--libfiles"); + builder.verbose(&format!("running {:?}", cmd)); + let files = output(&mut cmd); + for file in files.trim_end().split(' ') { builder.install(Path::new(file), dst_libdir, 0o644); } + !builder.config.dry_run + } else { + false } } /// Maybe add libLLVM.so to the target lib-dir for linking. pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib"); - maybe_install_llvm(builder, target, &dst_libdir); + // We do not need to copy LLVM files into the sysroot if it is not + // dynamically linked; it is already included into librustc_llvm + // statically. + if builder.config.llvm_link_shared { + maybe_install_llvm(builder, target, &dst_libdir); + } } /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself. pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target })); - maybe_install_llvm(builder, target, &dst_libdir); + // We do not need to copy LLVM files into the sysroot if it is not + // dynamically linked; it is already included into librustc_llvm + // statically. + if builder.config.llvm_link_shared { + maybe_install_llvm(builder, target, &dst_libdir); + } } #[derive(Clone, Debug, Eq, Hash, PartialEq)] @@ -1973,7 +1982,10 @@ impl Step for RustDev { // `$ORIGIN/../lib` can find it. It may also be used as a dependency // of `rustc-dev` to support the inherited `-lLLVM` when using the // compiler libraries. - maybe_install_llvm(builder, target, &tarball.image_dir().join("lib")); + let dst_libdir = tarball.image_dir().join("lib"); + maybe_install_llvm(builder, target, &dst_libdir); + let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" }; + t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir); Some(tarball.generate()) } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index b29ecd65401..fb5b058cb4d 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/80087 +Last change is for: https://github.com/rust-lang/rust/pull/80932 diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6412df3fd90..609ac8b3669 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -171,7 +171,6 @@ impl Step for Llvm { .define("LLVM_TARGETS_TO_BUILD", llvm_targets) .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) .define("LLVM_INCLUDE_EXAMPLES", "OFF") - .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") -- cgit 1.4.1-3-g733a5 From 5c4adbe1e12c804a03146e351e06f666f0fe1fdf Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 13 Jan 2021 09:32:48 -0500 Subject: Add all tier 1 platforms to supported platforms for "if-available" ... and update the comment in `config.toml.example` --- config.toml.example | 8 +++++--- src/bootstrap/bootstrap.py | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/config.toml.example b/config.toml.example index 9e08ce9b27e..55b20adabd0 100644 --- a/config.toml.example +++ b/config.toml.example @@ -35,9 +35,11 @@ changelog-seen = 2 # Unless you're developing for a target where Rust CI doesn't build a compiler # toolchain or changing LLVM locally, you probably want to set this to true. # -# It's currently false by default due to being newly added; please file bugs if -# enabling this did not work for you on x86_64-unknown-linux-gnu. -# Other target triples are currently not supported; see #77084. +# This is false by default so that distributions don't unexpectedly download +# LLVM from the internet. +# +# All tier 1 targets are currently supported; set this to `"if-supported"` if +# you are not sure whether you're on a tier 1 target. # # We also currently only support this when building LLVM for the build triple. # diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6d2d7bbbef9..5350c9eefe7 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -465,8 +465,21 @@ class RustBuild(object): def downloading_llvm(self): opt = self.get_toml('download-ci-llvm', 'llvm') + # This is currently all tier 1 targets (since others may not have CI + # artifacts) + # https://doc.rust-lang.org/rustc/platform-support.html#tier-1 + supported_platforms = [ + "aarch64-unknown-linux-gnu", + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + ] return opt == "true" \ - or (opt == "if-available" and self.build == "x86_64-unknown-linux-gnu") + or (opt == "if-available" and self.build in supported_platforms) def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None): if date is None: -- cgit 1.4.1-3-g733a5 From 8b702e02c06aa5af92f213ce69e810e35dd606db Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 15 Jan 2021 21:43:23 -0500 Subject: Support non-stage0 check --- src/bootstrap/check.rs | 30 ++++++++++++++++++++++-------- src/bootstrap/flags.rs | 6 +----- 2 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 72a979338a5..8d63473acac 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -73,7 +73,7 @@ impl Step for Std { fn run(self, builder: &Builder<'_>) { let target = self.target; - let compiler = builder.compiler(0, builder.config.build); + let compiler = builder.compiler(builder.top_stage, builder.config.build); let mut cargo = builder.cargo( compiler, @@ -94,9 +94,13 @@ impl Step for Std { true, ); - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); - add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); + // We skip populating the sysroot in non-zero stage because that'll lead + // to rlib/rmeta conflicts if std gets built during this session. + if compiler.stage == 0 { + let libdir = builder.sysroot_libdir(compiler, target); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); + } // Then run cargo again, once we've put the rmeta files for the library // crates into the sysroot. This is needed because e.g., core's tests @@ -163,10 +167,20 @@ impl Step for Rustc { /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); + let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; - builder.ensure(Std { target }); + if compiler.stage != 0 { + // If we're not in stage 0, then we won't have a std from the beta + // compiler around. That means we need to make sure there's one in + // the sysroot for the compiler to find. Otherwise, we're going to + // fail when building crates that need to generate code (e.g., build + // scripts and their dependencies). + builder.ensure(crate::compile::Std { target: compiler.host, compiler }); + builder.ensure(crate::compile::Std { target, compiler }); + } else { + builder.ensure(Std { target }); + } let mut cargo = builder.cargo( compiler, @@ -225,7 +239,7 @@ impl Step for CodegenBackend { } fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); + let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; let backend = self.backend; @@ -280,7 +294,7 @@ macro_rules! tool_check_step { } fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); + let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; builder.ensure(Rustc { target }); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d6a45f1c170..55062e11e02 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -614,14 +614,10 @@ Arguments: }; if let Subcommand::Check { .. } = &cmd { - if matches.opt_str("stage").is_some() { - println!("--stage not supported for x.py check, always treated as stage 0"); - process::exit(1); - } if matches.opt_str("keep-stage").is_some() || matches.opt_str("keep-stage-std").is_some() { - println!("--keep-stage not supported for x.py check, only one stage available"); + println!("--keep-stage not yet supported for x.py check"); process::exit(1); } } -- cgit 1.4.1-3-g733a5 From c17ed34da1b3298ec428aa9655fd5a0e18ecbaf8 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 15 Jan 2021 22:34:00 -0500 Subject: Print which stage is being checked (now that it may not be stage0) --- src/bootstrap/check.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 8d63473acac..c19bb536ce8 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -84,7 +84,10 @@ impl Step for Std { ); std_cargo(builder, target, compiler.stage, &mut cargo); - builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); + builder.info(&format!( + "Checking stage{} std artifacts ({} -> {})", + builder.top_stage, &compiler.host, target + )); run_cargo( builder, cargo, @@ -128,8 +131,8 @@ impl Step for Std { } builder.info(&format!( - "Checking std test/bench/example targets ({} -> {})", - &compiler.host, target + "Checking stage{} std test/bench/example targets ({} -> {})", + builder.top_stage, &compiler.host, target )); run_cargo( builder, @@ -201,7 +204,10 @@ impl Step for Rustc { cargo.arg("-p").arg(krate.name); } - builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); + builder.info(&format!( + "Checking stage{} compiler artifacts ({} -> {})", + builder.top_stage, &compiler.host, target + )); run_cargo( builder, cargo, @@ -258,8 +264,8 @@ impl Step for CodegenBackend { rustc_cargo_env(builder, &mut cargo, target); builder.info(&format!( - "Checking {} artifacts ({} -> {})", - backend, &compiler.host.triple, target.triple + "Checking stage{} {} artifacts ({} -> {})", + builder.top_stage, backend, &compiler.host.triple, target.triple )); run_cargo( @@ -315,7 +321,8 @@ macro_rules! tool_check_step { } builder.info(&format!( - "Checking {} artifacts ({} -> {})", + "Checking stage{} {} artifacts ({} -> {})", + builder.top_stage, stringify!($name).to_lowercase(), &compiler.host.triple, target.triple -- cgit 1.4.1-3-g733a5 From 53989e449d540ea0fbf9468bb133502835e07125 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 15 Jan 2021 22:41:39 -0500 Subject: Allow configuring the default stage for `x.py check` --- src/bootstrap/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index f4d89a89c14..8072df795ca 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -377,6 +377,7 @@ struct Build { configure_args: Option>, local_rebuild: Option, print_step_timings: Option, + check_stage: Option, doc_stage: Option, build_stage: Option, test_stage: Option, @@ -676,6 +677,7 @@ impl Config { // See https://github.com/rust-lang/compiler-team/issues/326 config.stage = match config.cmd { + Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0), Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0), Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1), Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1), @@ -685,7 +687,6 @@ impl Config { // These are all bootstrap tools, which don't depend on the compiler. // The stage we pass shouldn't matter, but use 0 just in case. Subcommand::Clean { .. } - | Subcommand::Check { .. } | Subcommand::Clippy { .. } | Subcommand::Fix { .. } | Subcommand::Run { .. } -- cgit 1.4.1-3-g733a5 From 15f0921d0c0d95c009bee7d9cd9921306b78615c Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 22 Nov 2020 13:57:11 +0100 Subject: correctly deal with late-bound lifetimes in anon consts --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 3 +- .../src/borrow_check/universal_regions.rs | 8 +++--- compiler/rustc_resolve/src/late/lifetimes.rs | 32 ++++++++++++++++++++-- .../const-generics/late-bound-vars/in_closure.rs | 18 ++++++++++++ .../ui/const-generics/late-bound-vars/simple.rs | 16 +++++++++++ 6 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/const-generics/late-bound-vars/in_closure.rs create mode 100644 src/test/ui/const-generics/late-bound-vars/simple.rs (limited to 'src') diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9770e67f2d2..0a9f740d53a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1316,7 +1316,7 @@ rustc_queries! { desc { "looking up a named region" } } query is_late_bound_map(_: LocalDefId) -> - Option<&'tcx FxHashSet> { + Option<(LocalDefId, &'tcx FxHashSet)> { desc { "testing if a region is late bound" } } query object_lifetime_defaults_map(_: LocalDefId) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a355242f5ce..148ac604596 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2578,7 +2578,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id)) + self.is_late_bound_map(id.owner) + .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) } pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs index c1a0d9856b7..02d951b70e2 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs @@ -788,13 +788,13 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { - for late_bound in late_bounds.iter() { - let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound }; + if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) { + for &late_bound in late_bounds.iter() { + let hir_id = HirId { owner, local_id: late_bound }; let name = tcx.hir().name(hir_id); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: fn_def_id, + scope: owner.to_def_id(), bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name), })); f(liberated_region); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index aab5c3cf8f5..1be06a44687 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -11,7 +11,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE}; +use rustc_hir::hir_id::ItemLocalId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}; @@ -20,6 +21,7 @@ use rustc_middle::middle::resolve_lifetime::*; use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::borrow::Cow; @@ -284,7 +286,7 @@ pub fn provide(providers: &mut ty::query::Providers) { resolve_lifetimes, named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), - is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id), + is_late_bound_map, object_lifetime_defaults_map: |tcx, id| { tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) }, @@ -320,6 +322,32 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes { rl } +fn is_late_bound_map<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> Option<(LocalDefId, &'tcx FxHashSet)> { + match tcx.def_kind(def_id) { + DefKind::AnonConst => { + let mut def_id = tcx + .parent(def_id.to_def_id()) + .unwrap_or_else(|| bug!("anon const or closure without a parent")); + // We search for the next outer anon const or fn here + // while skipping closures. + // + // Note that for `AnonConst` we still just recurse until we + // find a function body, but who cares :shrug: + while tcx.is_closure(def_id) { + def_id = tcx + .parent(def_id) + .unwrap_or_else(|| bug!("anon const or closure without a parent")); + } + + tcx.is_late_bound_map(def_id.expect_local()) + } + _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)), + } +} + fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { let krate = tcx.hir().krate(); let mut map = NamedRegionMap { diff --git a/src/test/ui/const-generics/late-bound-vars/in_closure.rs b/src/test/ui/const-generics/late-bound-vars/in_closure.rs new file mode 100644 index 00000000000..0aaeaffb4cb --- /dev/null +++ b/src/test/ui/const-generics/late-bound-vars/in_closure.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(const_generics)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _ = || { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; + }; +} + +fn main() { + test(); +} diff --git a/src/test/ui/const-generics/late-bound-vars/simple.rs b/src/test/ui/const-generics/late-bound-vars/simple.rs new file mode 100644 index 00000000000..2c411a3bdc5 --- /dev/null +++ b/src/test/ui/const-generics/late-bound-vars/simple.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(const_generics)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; +} + +fn main() { + test(); +} -- cgit 1.4.1-3-g733a5 From 7f9a2cfa1b91b8525907582a42d896dcd2fa176b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Dec 2020 19:34:04 +0300 Subject: resolve: Reject ambiguity built-in attr vs different built-in attr --- compiler/rustc_hir/src/def.rs | 7 ++++--- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 12 +++++++++--- src/test/ui/proc-macro/ambiguous-builtin-attrs.rs | 6 +++++- src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr | 16 +++++++++++++++- 5 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 4ede9d67b74..a81eb747a33 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -5,6 +5,7 @@ use rustc_ast as ast; use rustc_ast::NodeId; use rustc_macros::HashStable_Generic; use rustc_span::hygiene::MacroKind; +use rustc_span::Symbol; use std::array::IntoIter; use std::fmt::Debug; @@ -34,7 +35,7 @@ pub enum CtorKind { #[derive(HashStable_Generic)] pub enum NonMacroAttrKind { /// Single-segment attribute defined by the language (`#[inline]`) - Builtin, + Builtin(Symbol), /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`). Tool, /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). @@ -371,7 +372,7 @@ impl CtorKind { impl NonMacroAttrKind { pub fn descr(self) -> &'static str { match self { - NonMacroAttrKind::Builtin => "built-in attribute", + NonMacroAttrKind::Builtin(..) => "built-in attribute", NonMacroAttrKind::Tool => "tool attribute", NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => { "derive helper attribute" @@ -393,7 +394,7 @@ impl NonMacroAttrKind { NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => true, - NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false, + NonMacroAttrKind::Builtin(..) | NonMacroAttrKind::Registered => false, } } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4f8047ac2df..69fb6870d2c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -683,7 +683,7 @@ impl<'a> Resolver<'a> { )); } Scope::BuiltinAttrs => { - let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin); + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty)); if filter_fn(res) { suggestions.extend( BUILTIN_ATTRIBUTES diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 5c74094ecd3..5d6120cd310 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -757,7 +757,11 @@ impl<'a> Resolver<'a> { } Scope::BuiltinAttrs => { if is_builtin_attr_name(ident.name) { - ok(Res::NonMacroAttr(NonMacroAttrKind::Builtin), DUMMY_SP, this.arenas) + ok( + Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)), + DUMMY_SP, + this.arenas, + ) } else { Err(Determinacy::Determined) } @@ -810,13 +814,15 @@ impl<'a> Resolver<'a> { // Found another solution, if the first one was "weak", report an error. let (res, innermost_res) = (binding.res(), innermost_binding.res()); if res != innermost_res { - let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin); + let is_builtin = |res| { + matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..))) + }; let derive_helper_compat = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat); let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) - } else if innermost_res == builtin || res == builtin { + } else if is_builtin(innermost_res) || is_builtin(res) { Some(AmbiguityKind::BuiltinAttr) } else if innermost_res == derive_helper_compat || res == derive_helper_compat diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs index 142efb3c6cd..5f45f6892d2 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -1,5 +1,5 @@ +// edition:2018 // aux-build:builtin-attrs.rs - #![feature(decl_macro)] //~ ERROR `feature` is ambiguous extern crate builtin_attrs; @@ -31,3 +31,7 @@ fn main() { Bench; NonExistent; //~ ERROR cannot find value `NonExistent` in this scope } + +use deny as allow; +#[allow(unused)] //~ ERROR `allow` is ambiguous (built-in attribute vs any other name) +fn builtin_renamed() {} diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr index 276ee1cfd35..dfd60dc92cc 100644 --- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr +++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -60,6 +60,20 @@ LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ = help: use `crate::repr` to refer to this attribute macro unambiguously +error[E0659]: `allow` is ambiguous (built-in attribute vs any other name) + --> $DIR/ambiguous-builtin-attrs.rs:36:3 + | +LL | #[allow(unused)] + | ^^^^^ ambiguous name + | + = note: `allow` could refer to a built-in attribute +note: `allow` could also refer to the built-in attribute imported here + --> $DIR/ambiguous-builtin-attrs.rs:35:5 + | +LL | use deny as allow; + | ^^^^^^^^^^^^^ + = help: use `crate::allow` to refer to this built-in attribute unambiguously + error[E0659]: `feature` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:3:4 | @@ -80,7 +94,7 @@ error[E0517]: attribute should be applied to a struct, enum, or union LL | fn non_macro_expanded_location<#[repr(C)] T>() { | ^ - not a struct, enum, or union -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0425, E0517, E0659. For more information about an error, try `rustc --explain E0425`. -- cgit 1.4.1-3-g733a5 From c127ed6e97535e4a20873d6cfe4fff364a2b9d9b Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Sat, 16 Jan 2021 16:32:51 +0100 Subject: Force vec! to expressions only --- library/alloc/src/lib.rs | 8 ++++++++ library/alloc/src/macros.rs | 8 ++++---- src/test/ui/macros/vec-macro-in-pattern.rs | 10 ++++++++++ src/test/ui/macros/vec-macro-in-pattern.stderr | 10 ++++++++++ src/test/ui/suggestions/vec-macro-in-pattern.fixed | 8 -------- src/test/ui/suggestions/vec-macro-in-pattern.rs | 8 -------- src/test/ui/suggestions/vec-macro-in-pattern.stderr | 16 ---------------- src/test/ui/type/ascription/issue-47666.stderr | 2 +- 8 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/macros/vec-macro-in-pattern.rs create mode 100644 src/test/ui/macros/vec-macro-in-pattern.stderr delete mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.fixed delete mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.rs delete mode 100644 src/test/ui/suggestions/vec-macro-in-pattern.stderr (limited to 'src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d0bfa038aa1..14a10aac061 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,6 +140,7 @@ #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] +#![feature(decl_macro)] // Allow testing this library #[cfg(test)] @@ -193,4 +194,11 @@ mod std { #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] pub mod __export { pub use core::format_args; + + /// Force AST node to an expression to improve diagnostics in pattern position. + #[rustc_macro_transparency = "semitransparent"] + #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] + pub macro force_expr($e:expr) { + $e + } } diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 7d4eff6185d..3a46763c3f6 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -37,16 +37,16 @@ #[cfg(not(test))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable(box_syntax)] +#[allow_internal_unstable(box_syntax, liballoc_internals)] macro_rules! vec { () => ( - $crate::vec::Vec::new() + $crate::__export::force_expr!($crate::vec::Vec::new()) ); ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) + $crate::__export::force_expr!($crate::vec::from_elem($elem, $n)) ); ($($x:expr),+ $(,)?) => ( - <[_]>::into_vec(box [$($x),+]) + $crate::__export::force_expr!(<[_]>::into_vec(box [$($x),+])) ); } diff --git a/src/test/ui/macros/vec-macro-in-pattern.rs b/src/test/ui/macros/vec-macro-in-pattern.rs new file mode 100644 index 00000000000..ce4298b8bb3 --- /dev/null +++ b/src/test/ui/macros/vec-macro-in-pattern.rs @@ -0,0 +1,10 @@ +// This is a regression test for #61933 +// Verify that the vec![] macro may not be used in patterns +// and that the resulting diagnostic is actually helpful. + +fn main() { + match Some(vec![42]) { + Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns + _ => {} + } +} diff --git a/src/test/ui/macros/vec-macro-in-pattern.stderr b/src/test/ui/macros/vec-macro-in-pattern.stderr new file mode 100644 index 00000000000..3dabebfdaa2 --- /dev/null +++ b/src/test/ui/macros/vec-macro-in-pattern.stderr @@ -0,0 +1,10 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/vec-macro-in-pattern.rs:7:14 + | +LL | Some(vec![43]) => {} + | ^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.fixed b/src/test/ui/suggestions/vec-macro-in-pattern.fixed deleted file mode 100644 index e1695d6820a..00000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.fixed +++ /dev/null @@ -1,8 +0,0 @@ -// run-rustfix -fn main() { - // everything after `.as_ref` should be suggested - match Some(vec![3]).as_ref().map(|v| v.as_slice()) { - Some([_x]) => (), //~ ERROR unexpected `(` after qualified path - _ => (), - } -} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs deleted file mode 100644 index 4843629fbcf..00000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-rustfix -fn main() { - // everything after `.as_ref` should be suggested - match Some(vec![3]).as_ref().map(|v| v.as_slice()) { - Some(vec![_x]) => (), //~ ERROR unexpected `(` after qualified path - _ => (), - } -} diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr deleted file mode 100644 index f9d0464ac88..00000000000 --- a/src/test/ui/suggestions/vec-macro-in-pattern.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: unexpected `(` after qualified path - --> $DIR/vec-macro-in-pattern.rs:5:14 - | -LL | Some(vec![_x]) => (), - | ^^^^^^^^ - | | - | unexpected `(` after qualified path - | the qualified path - | in this macro invocation - | help: use a slice pattern here instead: `[_x]` - | - = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index ba393ff1a20..755eec23c2e 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -1,4 +1,4 @@ -error: expected type, found reserved keyword `box` +error: expected type, found `<[_]>::into_vec(box [0, 1])` --> $DIR/issue-47666.rs:3:25 | LL | let _ = Option:Some(vec![0, 1]); -- cgit 1.4.1-3-g733a5