about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-03-22 22:29:54 +0100
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-03-22 22:29:54 +0100
commit645fedd183a341b5ab5553d4d35ce9140276371f (patch)
tree2a57a4c373b843a84a6e9bb5e2c2950d51730371
parent1902d1e0de179498d0cb7fd4856d1e0ffcd52095 (diff)
downloadrust-645fedd183a341b5ab5553d4d35ce9140276371f.tar.gz
rust-645fedd183a341b5ab5553d4d35ce9140276371f.zip
correctly handle const params in type_of
-rw-r--r--src/librustc_hir/def.rs1
-rw-r--r--src/librustc_typeck/collect/type_of.rs32
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue70273-assoc-fn.rs17
-rw-r--r--src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr8
-rw-r--r--src/test/ui/const-generics/type_of_anon_const.rs21
-rw-r--r--src/test/ui/const-generics/type_of_anon_const.stderr8
7 files changed, 73 insertions, 15 deletions
diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs
index 696aa5c6f7d..3334cc32a52 100644
--- a/src/librustc_hir/def.rs
+++ b/src/librustc_hir/def.rs
@@ -159,6 +159,7 @@ impl DefKind {
     }
 }
 
+/// The resolution of a path or export.
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum Res<Id = hir::HirId> {
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 55642dfb455..eec87f3e3b0 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -235,29 +235,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     };
 
                     if let Some(path) = path {
-                        let arg_index = path
+                        // We've encountered an `AnonConst` in some path, so we need to
+                        // figure out which generic parameter it corresponds to and return
+                        // the relevant type.
+
+                        let (arg_index, segment) = path
                             .segments
                             .iter()
-                            .filter_map(|seg| seg.args.as_ref())
-                            .map(|generic_args| generic_args.args)
-                            .find_map(|args| {
+                            .filter_map(|seg| seg.args.as_ref().map(|args| (args.args, seg)))
+                            .find_map(|(args, seg)| {
                                 args.iter()
                                     .filter(|arg| arg.is_const())
                                     .enumerate()
                                     .filter(|(_, arg)| arg.id() == hir_id)
-                                    .map(|(index, _)| index)
+                                    .map(|(index, _)| (index, seg))
                                     .next()
                             })
                             .unwrap_or_else(|| {
                                 bug!("no arg matching AnonConst in path");
                             });
 
-                        // We've encountered an `AnonConst` in some path, so we need to
-                        // figure out which generic parameter it corresponds to and return
-                        // the relevant type.
-                        let generics = match path.res {
-                            Res::Def(DefKind::Ctor(..), def_id)
-                            | Res::Def(DefKind::AssocTy, def_id) => {
+                        // try to use the segment resolution if it is valid, otherwise we
+                        // default to the path resolution.
+                        let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
+                        let generics = match res {
+                            Res::Def(DefKind::Ctor(..) | DefKind::AssocTy, def_id) => {
                                 tcx.generics_of(tcx.parent(def_id).unwrap())
                             }
                             Res::Def(_, def_id) => tcx.generics_of(def_id),
@@ -265,8 +267,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                 tcx.sess.delay_span_bug(
                                     DUMMY_SP,
                                     &format!(
-                                        "unexpected const parent path def, parent: {:?}, def: {:?}",
-                                        parent_node, res
+                                        "unexpected anon const res {:?} in path: {:?}",
+                                        res, path,
                                     ),
                                 );
                                 return tcx.types.err;
@@ -291,8 +293,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                 tcx.sess.delay_span_bug(
                                     DUMMY_SP,
                                     &format!(
-                                        "missing generic parameter for `AnonConst`, parent {:?}",
-                                        parent_node
+                                        "missing generic parameter for `AnonConst`, parent: {:?}, res: {:?}",
+                                        parent_node, res
                                     ),
                                 );
                                 tcx.types.err
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index e487e0d265c..fd854c75018 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -62,6 +62,7 @@ This API is completely unstable and subject to change.
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
+#![feature(or_patterns)]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![feature(slice_partition_dedup)]
diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs
new file mode 100644
index 00000000000..a192ddea9c6
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+trait T<const A: usize> {
+    fn f();
+}
+struct S;
+
+impl T<0usize> for S {
+    fn f() {}
+}
+
+fn main() {
+    let _err = <S as T<0usize>>::f();
+}
diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr
new file mode 100644
index 00000000000..64007ade0f2
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue70273-assoc-fn.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/type_of_anon_const.rs b/src/test/ui/const-generics/type_of_anon_const.rs
new file mode 100644
index 00000000000..776084b77a5
--- /dev/null
+++ b/src/test/ui/const-generics/type_of_anon_const.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+trait T<const A: usize> {
+    fn l<const N: bool>() -> usize;
+    fn r<const N: bool>() -> bool;
+}
+
+struct S;
+
+impl<const N: usize> T<N> for S {
+    fn l<const M: bool>() -> usize { N }
+    fn r<const M: bool>() -> bool { M }
+}
+
+fn main() {
+   assert_eq!(<S as T<123>>::l::<true>(), 123);
+   assert!(<S as T<123>>::r::<true>());
+}
diff --git a/src/test/ui/const-generics/type_of_anon_const.stderr b/src/test/ui/const-generics/type_of_anon_const.stderr
new file mode 100644
index 00000000000..495d34ce09b
--- /dev/null
+++ b/src/test/ui/const-generics/type_of_anon_const.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/type_of_anon_const.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+