about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-05-25 17:14:44 +0000
committerbors <bors@rust-lang.org>2020-05-25 17:14:44 +0000
commitf93bb2a50b37bc8bafe4d960e2afd839eaa854ed (patch)
treed1e3ebb520e2ccf6b1260505a4a1e8ea9da48a37 /src
parenta0f06d11ae7fe29c8e263e2a5d8cd41b372f0283 (diff)
parentaa8d64b005ab347477632bde4d33837385d39c80 (diff)
downloadrust-f93bb2a50b37bc8bafe4d960e2afd839eaa854ed.tar.gz
rust-f93bb2a50b37bc8bafe4d960e2afd839eaa854ed.zip
Auto merge of #72575 - Dylan-DPC:rollup-zo679hv, r=Dylan-DPC
Rollup of 4 pull requests

Successful merges:

 - #72153 (exhaustively check `ty::Kind` during structural match checking)
 - #72308 (Emit a better diagnostic when function actually has a 'self' parameter)
 - #72560 (Enable `glacier` command via triagebot)
 - #72567 (Clean up E0608 explanation)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/librustc_error_codes/error_codes/E0608.md2
-rw-r--r--src/librustc_mir_build/hair/pattern/const_to_pat.rs14
-rw-r--r--src/librustc_resolve/late.rs5
-rw-r--r--src/librustc_resolve/late/diagnostics.rs11
-rw-r--r--src/librustc_trait_selection/traits/structural_match.rs53
-rw-r--r--src/test/ui/hygiene/missing-self-diag.rs23
-rw-r--r--src/test/ui/hygiene/missing-self-diag.stderr17
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs20
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match.rs21
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match.stderr8
11 files changed, 171 insertions, 11 deletions
diff --git a/src/librustc_error_codes/error_codes/E0608.md b/src/librustc_error_codes/error_codes/E0608.md
index 598f1e655e9..d0ebc3a26f0 100644
--- a/src/librustc_error_codes/error_codes/E0608.md
+++ b/src/librustc_error_codes/error_codes/E0608.md
@@ -1,4 +1,4 @@
-An attempt to index into a type which doesn't implement the `std::ops::Index`
+An attempt to use index on a type which doesn't implement the `std::ops::Index`
 trait was performed.
 
 Erroneous code example:
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 28ec2ca13d5..9e3f75fdc07 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -124,8 +124,20 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                     traits::NonStructuralMatchTy::Dynamic => {
                         "trait objects cannot be used in patterns".to_string()
                     }
+                    traits::NonStructuralMatchTy::Opaque => {
+                        "opaque types cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTy::Generator => {
+                        "generators cannot be used in patterns".to_string()
+                    }
                     traits::NonStructuralMatchTy::Param => {
-                        bug!("use of constant whose type is a parameter inside a pattern")
+                        bug!("use of a constant whose type is a parameter inside a pattern")
+                    }
+                    traits::NonStructuralMatchTy::Projection => {
+                        bug!("use of a constant whose type is a projection inside a pattern")
+                    }
+                    traits::NonStructuralMatchTy::Foreign => {
+                        bug!("use of a value of a foreign type inside a pattern")
                     }
                 };
 
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index e541920e89e..477e3be5cc2 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -347,7 +347,7 @@ struct DiagnosticMetadata<'ast> {
     currently_processing_generics: bool,
 
     /// The current enclosing function (used for better errors).
-    current_function: Option<Span>,
+    current_function: Option<(FnKind<'ast>, Span)>,
 
     /// A list of labels as of yet unused. Labels will be removed from this map when
     /// they are used (in a `break` or `continue` statement)
@@ -466,7 +466,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
             FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind,
             FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind,
         };
-        let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
+        let previous_value =
+            replace(&mut self.diagnostic_metadata.current_function, Some((fn_kind, sp)));
         debug!("(resolving function) entering function");
         let declaration = fn_kind.decl();
 
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index dc92b465c2b..b1a1f8725a1 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -195,8 +195,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                 _ => "`self` value is a keyword only available in methods with a `self` parameter"
                      .to_string(),
             });
-            if let Some(span) = &self.diagnostic_metadata.current_function {
-                err.span_label(*span, "this function doesn't have a `self` parameter");
+            if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
+                // The current function has a `self' parameter, but we were unable to resolve
+                // a reference to `self`. This can only happen if the `self` identifier we
+                // are resolving came from a different hygiene context.
+                if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
+                    err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
+                } else {
+                    err.span_label(*span, "this function doesn't have a `self` parameter");
+                }
             }
             return (err, Vec::new());
         }
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index eb63505b69b..b877049fcf6 100644
--- a/src/librustc_trait_selection/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
@@ -13,6 +13,10 @@ pub enum NonStructuralMatchTy<'tcx> {
     Adt(&'tcx AdtDef),
     Param,
     Dynamic,
+    Foreign,
+    Opaque,
+    Generator,
+    Projection,
 }
 
 /// This method traverses the structure of `ty`, trying to find an
@@ -143,6 +147,22 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 self.found = Some(NonStructuralMatchTy::Dynamic);
                 return true; // Stop visiting.
             }
+            ty::Foreign(_) => {
+                self.found = Some(NonStructuralMatchTy::Foreign);
+                return true; // Stop visiting.
+            }
+            ty::Opaque(..) => {
+                self.found = Some(NonStructuralMatchTy::Opaque);
+                return true; // Stop visiting.
+            }
+            ty::Projection(..) => {
+                self.found = Some(NonStructuralMatchTy::Projection);
+                return true; // Stop visiting.
+            }
+            ty::Generator(..) | ty::GeneratorWitness(..) => {
+                self.found = Some(NonStructuralMatchTy::Generator);
+                return true; // Stop visiting.
+            }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
                 // `*const _`/`*mut _`, so skip `super_visit_with`.
@@ -159,14 +179,14 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 // structural equality on `T` does not recur into the raw
                 // pointer. Therefore, one can still use `C` in a pattern.
 
-                // (But still tell caller to continue search.)
+                // (But still tell the caller to continue search.)
                 return false;
             }
             ty::FnDef(..) | ty::FnPtr(..) => {
-                // types of formals and return in `fn(_) -> _` are also irrelevant;
+                // Types of formals and return in `fn(_) -> _` are also irrelevant;
                 // so we do not recur into them via `super_visit_with`
                 //
-                // (But still tell caller to continue search.)
+                // (But still tell the caller to continue search.)
                 return false;
             }
             ty::Array(_, n)
@@ -174,17 +194,40 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
             {
                 // rust-lang/rust#62336: ignore type of contents
                 // for empty array.
+                //
+                // (But still tell the caller to continue search.)
                 return false;
             }
-            _ => {
+            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
+                // These primitive types are always structural match.
+                //
+                // `Never` is kind of special here, but as it is not inhabitable, this should be fine.
+                //
+                // (But still tell the caller to continue search.)
+                return false;
+            }
+
+            ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
+                // First check all contained types and then tell the caller to continue searching.
                 ty.super_visit_with(self);
                 return false;
             }
+            ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
+                bug!("unexpected type during structural-match checking: {:?}", ty);
+            }
+            ty::Error => {
+                self.tcx().sess.delay_span_bug(self.span, "ty::Error in structural-match check");
+                // We still want to check other types after encountering an error,
+                // as this may still emit relevant errors.
+                //
+                // So we continue searching here.
+                return false;
+            }
         };
 
         if !self.seen.insert(adt_def.did) {
             debug!("Search already seen adt_def: {:?}", adt_def);
-            // let caller continue its search
+            // Let caller continue its search.
             return false;
         }
 
diff --git a/src/test/ui/hygiene/missing-self-diag.rs b/src/test/ui/hygiene/missing-self-diag.rs
new file mode 100644
index 00000000000..f934f793c7f
--- /dev/null
+++ b/src/test/ui/hygiene/missing-self-diag.rs
@@ -0,0 +1,23 @@
+// Regression test for issue #66898
+// Tests that we don't emit a nonsensical error message
+// when a macro invocation tries to access `self` from a function
+// that has a 'self' parameter
+
+pub struct Foo;
+
+macro_rules! call_bar {
+    () => {
+        self.bar(); //~ ERROR expected value
+    }
+}
+
+impl Foo {
+    pub fn foo(&self) {
+        call_bar!();
+    }
+
+    pub fn bar(&self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/missing-self-diag.stderr b/src/test/ui/hygiene/missing-self-diag.stderr
new file mode 100644
index 00000000000..075d6b76bb7
--- /dev/null
+++ b/src/test/ui/hygiene/missing-self-diag.stderr
@@ -0,0 +1,17 @@
+error[E0424]: expected value, found module `self`
+  --> $DIR/missing-self-diag.rs:10:9
+   |
+LL |           self.bar();
+   |           ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+...
+LL | /     pub fn foo(&self) {
+LL | |         call_bar!();
+   | |         ------------ in this macro invocation
+LL | |     }
+   | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0424`.
diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
new file mode 100644
index 00000000000..479d6cd9af7
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
@@ -0,0 +1,20 @@
+#![feature(const_fn, type_alias_impl_trait)]
+
+type Bar = impl Send;
+
+// While i32 is structural-match, we do not want to leak this information.
+// (See https://github.com/rust-lang/rust/issues/72156)
+const fn leak_free() -> Bar {
+    7i32
+}
+const LEAK_FREE: Bar = leak_free();
+
+fn leak_free_test() {
+    match todo!() {
+        LEAK_FREE => (),
+        //~^ opaque types cannot be used in patterns
+        _ => (),
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
new file mode 100644
index 00000000000..ae0d8e8d423
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
@@ -0,0 +1,8 @@
+error: opaque types cannot be used in patterns
+  --> $DIR/structural-match-no-leak.rs:14:9
+   |
+LL |         LEAK_FREE => (),
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs
new file mode 100644
index 00000000000..481448d64b1
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/structural-match.rs
@@ -0,0 +1,21 @@
+#![feature(const_fn, type_alias_impl_trait)]
+
+type Foo = impl Send;
+
+// This is not structural-match
+struct A;
+
+const fn value() -> Foo {
+    A
+}
+const VALUE: Foo = value();
+
+fn test() {
+    match todo!() {
+        VALUE => (),
+        //~^ opaque types cannot be used in patterns
+        _ => (),
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr
new file mode 100644
index 00000000000..ad9036a87d1
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/structural-match.stderr
@@ -0,0 +1,8 @@
+error: opaque types cannot be used in patterns
+  --> $DIR/structural-match.rs:15:9
+   |
+LL |         VALUE => (),
+   |         ^^^^^
+
+error: aborting due to previous error
+