diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index dca676130b9a7..447ce46ee5c5c 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -28,6 +28,7 @@ use util::nodemap::FxHashMap; use syntax::ast; use syntax::symbol::Symbol; +use syntax_pos::Span; use hir::itemlikevisit::ItemLikeVisitor; use hir; @@ -104,17 +105,18 @@ struct LanguageItemCollector<'a, 'tcx: 'a> { impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { - if let Some(value) = extract(&item.attrs) { + if let Some((value, span)) = extract(&item.attrs) { let item_index = self.item_refs.get(&*value.as_str()).cloned(); if let Some(item_index) = item_index { let def_id = self.tcx.hir.local_def_id(item.id); self.collect_item(item_index, def_id); } else { - let span = self.tcx.hir.span(item.id); - span_err!(self.tcx.sess, span, E0522, - "definition of an unknown language item: `{}`.", - value); + let mut err = struct_span_err!(self.tcx.sess, span, E0522, + "definition of an unknown language item: `{}`", + value); + err.span_label(span, format!("definition of unknown language item `{}`", value)); + err.emit(); } } } @@ -177,11 +179,11 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { } } -pub fn extract(attrs: &[ast::Attribute]) -> Option { +pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { for attribute in attrs { if attribute.check_name("lang") { if let Some(value) = attribute.value_str() { - return Some(value) + return Some((value, attribute.span)); } } } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 50fb584070262..95e75b4f0646e 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -55,7 +55,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } pub fn link_name(attrs: &[ast::Attribute]) -> Option { - lang_items::extract(attrs).and_then(|name| { + lang_items::extract(attrs).and_then(|(name, _)| { $(if name == stringify!($name) { Some(Symbol::intern(stringify!($sym))) } else)* { @@ -129,7 +129,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_foreign_item(&mut self, i: &hir::ForeignItem) { - if let Some(lang_item) = lang_items::extract(&i.attrs) { + if let Some((lang_item, _)) = lang_items::extract(&i.attrs) { self.register(&lang_item.as_str(), i.span); } intravisit::walk_foreign_item(self, i) diff --git a/src/test/compile-fail/E0522.rs b/src/test/compile-fail/E0522.rs index 5103c83cafce3..3d4377853464b 100644 --- a/src/test/compile-fail/E0522.rs +++ b/src/test/compile-fail/E0522.rs @@ -11,6 +11,7 @@ #![feature(lang_items)] #[lang = "cookie"] -fn cookie() -> ! { //~ E0522 +fn cookie() -> ! { +//~^^ ERROR definition of an unknown language item: `cookie` [E0522] loop {} } diff --git a/src/test/ui/unknown-language-item.rs b/src/test/ui/unknown-language-item.rs new file mode 100644 index 0000000000000..3c2105997127d --- /dev/null +++ b/src/test/ui/unknown-language-item.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused)] +#![feature(lang_items)] + +#[lang = "foo"] +fn bar() -> ! { +//~^^ ERROR definition of an unknown language item: `foo` + loop {} +} + +fn main() {} diff --git a/src/test/ui/unknown-language-item.stderr b/src/test/ui/unknown-language-item.stderr new file mode 100644 index 0000000000000..c4b4a789c3dcc --- /dev/null +++ b/src/test/ui/unknown-language-item.stderr @@ -0,0 +1,8 @@ +error[E0522]: definition of an unknown language item: `foo` + --> $DIR/unknown-language-item.rs:14:1 + | +14 | #[lang = "foo"] + | ^^^^^^^^^^^^^^^ definition of unknown language item `foo` + +error: aborting due to previous error +