diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 9e95f0acfeb79..826ae836a906e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -734,6 +734,14 @@ impl<'hir> Map<'hir> { } } + pub fn is_const_scope(&self, hir_id: HirId) -> bool { + self.walk_parent_nodes(hir_id, |node| match *node { + Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true, + Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(), + _ => false, + }, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false) + } + /// If there is some error when walking the parents (e.g., a node does not /// have a parent in the map or a node can't be found), then we return the /// last good `NodeId` we found. Note that reaching the crate root (`id == 0`), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2e10300dced0e..8418658ab6878 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2288,6 +2288,15 @@ pub struct FnHeader { pub abi: Abi, } +impl FnHeader { + pub fn is_const(&self) -> bool { + match &self.constness { + Constness::Const => true, + _ => false, + } + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum ItemKind { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6249d6e56af68..689996ccb25a9 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -7,7 +7,7 @@ use syntax_pos::Span; use rustc::hir; use rustc::hir::def::Def; use rustc::hir::Node; -use rustc::hir::{Item, ItemKind, print}; +use rustc::hir::print; use rustc::ty::{self, Ty, AssociatedItem}; use rustc::ty::adjustment::AllowTwoPhase; use errors::{Applicability, DiagnosticBuilder}; @@ -550,14 +550,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { - let parent_id = self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id); - if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) { + if self.tcx.hir().is_const_scope(expr.hir_id) { // Shouldn't suggest `.into()` on `const`s. - if let Node::Item(Item { node: ItemKind::Const(_, _), .. }) = parent { - // FIXME(estebank): modify once we decide to suggest `as` casts - return false; - } - }; + // FIXME(estebank): modify once we decide to suggest `as` casts + return false; + } // If casting this expression to a given numeric type would be appropriate in case of a type // mismatch. diff --git a/src/test/ui/numeric/const-scope.rs b/src/test/ui/numeric/const-scope.rs new file mode 100644 index 0000000000000..053599a9bb9f1 --- /dev/null +++ b/src/test/ui/numeric/const-scope.rs @@ -0,0 +1,12 @@ +const C: i32 = 1i8; //~ ERROR mismatched types +const D: i8 = C; //~ ERROR mismatched types + +const fn foo() { + let c: i32 = 1i8; //~ ERROR mismatched types + let d: i8 = c; //~ ERROR mismatched types +} + +fn main() { + let c: i32 = 1i8; //~ ERROR mismatched types + let d: i8 = c; //~ ERROR mismatched types +} diff --git a/src/test/ui/numeric/const-scope.stderr b/src/test/ui/numeric/const-scope.stderr new file mode 100644 index 0000000000000..ead3a79da0270 --- /dev/null +++ b/src/test/ui/numeric/const-scope.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/const-scope.rs:1:16 + | +LL | const C: i32 = 1i8; + | ^^^ expected i32, found i8 + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:2:15 + | +LL | const D: i8 = C; + | ^ expected i8, found i32 + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:5:18 + | +LL | let c: i32 = 1i8; + | ^^^ expected i32, found i8 + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:6:17 + | +LL | let d: i8 = c; + | ^ expected i8, found i32 + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:10:18 + | +LL | let c: i32 = 1i8; + | ^^^ expected i32, found i8 +help: change the type of the numeric literal from `i8` to `i32` + | +LL | let c: i32 = 1i32; + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:11:17 + | +LL | let d: i8 = c; + | ^ expected i8, found i32 +help: you can convert an `i32` to `i8` or panic if it the converted value wouldn't fit + | +LL | let d: i8 = c.try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`.