Skip to content

Commit ddabd50

Browse files
committed
compare-method lint
1 parent f652651 commit ddabd50

24 files changed

+152
-67
lines changed

src/librustc/infer/error_reporting.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -646,13 +646,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
646646
};
647647

648648
if let SubregionOrigin::CompareImplMethodObligation {
649-
span, item_name, impl_item_def_id, trait_item_def_id
649+
span, item_name, impl_item_def_id, trait_item_def_id, lint_id
650650
} = origin {
651651
self.report_extra_impl_obligation(span,
652652
item_name,
653653
impl_item_def_id,
654654
trait_item_def_id,
655-
&format!("`{}: {}`", bound_kind, sub))
655+
&format!("`{}: {}`", bound_kind, sub),
656+
lint_id)
656657
.emit();
657658
return;
658659
}
@@ -977,12 +978,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
977978
infer::CompareImplMethodObligation { span,
978979
item_name,
979980
impl_item_def_id,
980-
trait_item_def_id } => {
981+
trait_item_def_id,
982+
lint_id } => {
981983
self.report_extra_impl_obligation(span,
982984
item_name,
983985
impl_item_def_id,
984986
trait_item_def_id,
985-
&format!("`{}: {}`", sup, sub))
987+
&format!("`{}: {}`", sup, sub),
988+
lint_id)
986989
}
987990
}
988991
}

src/librustc/infer/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ pub enum SubregionOrigin<'tcx> {
368368
item_name: ast::Name,
369369
impl_item_def_id: DefId,
370370
trait_item_def_id: DefId,
371+
372+
// this is `Some(_)` if this error arises from the bug fix for
373+
// #18937. This is a temporary measure.
374+
lint_id: Option<ast::NodeId>,
371375
},
372376
}
373377

@@ -1816,12 +1820,14 @@ impl<'tcx> SubregionOrigin<'tcx> {
18161820

18171821
traits::ObligationCauseCode::CompareImplMethodObligation { item_name,
18181822
impl_item_def_id,
1819-
trait_item_def_id } =>
1823+
trait_item_def_id,
1824+
lint_id } =>
18201825
SubregionOrigin::CompareImplMethodObligation {
18211826
span: cause.span,
18221827
item_name: item_name,
18231828
impl_item_def_id: impl_item_def_id,
18241829
trait_item_def_id: trait_item_def_id,
1830+
lint_id: lint_id,
18251831
},
18261832

18271833
_ => default(),

src/librustc/lint/builtin.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ declare_lint! {
198198
"patterns in functions without body were erroneously allowed"
199199
}
200200

201+
declare_lint! {
202+
pub EXTRA_REQUIREMENT_IN_IMPL,
203+
Warn,
204+
"detects extra requirements in impls that were erroneously allowed"
205+
}
206+
201207
/// Does nothing as a lint pass, but registers some `Lint`s
202208
/// which are used by other parts of the compiler.
203209
#[derive(Copy, Clone)]
@@ -235,7 +241,8 @@ impl LintPass for HardwiredLints {
235241
HR_LIFETIME_IN_ASSOC_TYPE,
236242
LIFETIME_UNDERSCORE,
237243
SAFE_EXTERN_STATICS,
238-
PATTERNS_IN_FNS_WITHOUT_BODY
244+
PATTERNS_IN_FNS_WITHOUT_BODY,
245+
EXTRA_REQUIREMENT_IN_IMPL
239246
)
240247
}
241248
}

src/librustc/lint/context.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use std::fmt;
4242
use syntax::attr;
4343
use syntax::parse::token::InternedString;
4444
use syntax::ast;
45-
use syntax_pos::Span;
45+
use syntax_pos::{MultiSpan, Span};
4646
use errors::{self, Diagnostic, DiagnosticBuilder};
4747
use hir;
4848
use hir::intravisit as hir_visit;
@@ -107,9 +107,12 @@ impl fmt::Debug for EarlyLint {
107107
}
108108

109109
impl EarlyLint {
110-
pub fn new(id: LintId, span: Span, msg: String) -> Self {
111-
let mut diagnostic = Diagnostic::new(errors::Level::Warning, &msg);
112-
diagnostic.set_span(span);
110+
pub fn new<M: EarlyLintMessage>(id: LintId, span: Span, msg: M) -> Self {
111+
let diagnostic = msg.into_diagnostic(span);
112+
EarlyLint { id: id, span: span, diagnostic: diagnostic }
113+
}
114+
115+
pub fn with_diagnostic(id: LintId, span: Span, diagnostic: Diagnostic) -> Self {
113116
EarlyLint { id: id, span: span, diagnostic: diagnostic }
114117
}
115118

@@ -120,7 +123,23 @@ impl EarlyLint {
120123
}
121124
}
122125

126+
pub trait EarlyLintMessage {
127+
fn into_diagnostic(self, span: Span) -> Diagnostic;
128+
}
123129

130+
impl EarlyLintMessage for String {
131+
fn into_diagnostic(self, span: Span) -> Diagnostic {
132+
let mut diagnostic = Diagnostic::new(errors::Level::Warning, &self);
133+
diagnostic.set_span(span);
134+
diagnostic
135+
}
136+
}
137+
138+
impl EarlyLintMessage for Diagnostic {
139+
fn into_diagnostic(self, _span: Span) -> Diagnostic {
140+
self
141+
}
142+
}
124143

125144
/// Extra information for a future incompatibility lint. See the call
126145
/// to `register_future_incompatible` in `librustc_lint/lib.rs` for
@@ -439,13 +458,15 @@ pub fn raw_emit_lint(sess: &Session,
439458
raw_struct_lint(sess, lints, lint, lvlsrc, span, msg).emit();
440459
}
441460

442-
pub fn raw_struct_lint<'a>(sess: &'a Session,
443-
lints: &LintStore,
444-
lint: &'static Lint,
445-
lvlsrc: LevelSource,
446-
span: Option<Span>,
447-
msg: &str)
448-
-> DiagnosticBuilder<'a> {
461+
pub fn raw_struct_lint<'a, S>(sess: &'a Session,
462+
lints: &LintStore,
463+
lint: &'static Lint,
464+
lvlsrc: LevelSource,
465+
span: Option<S>,
466+
msg: &str)
467+
-> DiagnosticBuilder<'a>
468+
where S: Into<MultiSpan>
469+
{
449470
let (mut level, source) = lvlsrc;
450471
if level == Allow {
451472
return sess.diagnostic().struct_dummy();

src/librustc/lint/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use hir;
4141

4242
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
4343
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
44-
raw_struct_lint, FutureIncompatibleInfo, EarlyLint};
44+
raw_struct_lint, FutureIncompatibleInfo, EarlyLint, EarlyLintMessage};
4545

4646
/// Specification of a single lint.
4747
#[derive(Copy, Clone, Debug)]

src/librustc/session/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,11 @@ impl Session {
258258
pub fn unimpl(&self, msg: &str) -> ! {
259259
self.diagnostic().unimpl(msg)
260260
}
261-
pub fn add_lint(&self,
262-
lint: &'static lint::Lint,
263-
id: ast::NodeId,
264-
sp: Span,
265-
msg: String) {
261+
pub fn add_lint<M: lint::EarlyLintMessage>(&self,
262+
lint: &'static lint::Lint,
263+
id: ast::NodeId,
264+
sp: Span,
265+
msg: M) {
266266
let lint_id = lint::LintId::of(lint);
267267
let mut lints = self.lints.borrow_mut();
268268
let early_lint = lint::EarlyLint::new(lint_id, sp, msg);

src/librustc/traits/error_reporting.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use super::{
2727
use fmt_macros::{Parser, Piece, Position};
2828
use hir::def_id::DefId;
2929
use infer::{self, InferCtxt, TypeOrigin};
30+
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3031
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
3132
use ty::error::ExpectedFound;
3233
use ty::fast_reject;
@@ -423,9 +424,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
423424
item_name: ast::Name,
424425
_impl_item_def_id: DefId,
425426
trait_item_def_id: DefId,
426-
requirement: &fmt::Display)
427+
requirement: &fmt::Display,
428+
lint_id: Option<ast::NodeId>) // (*)
427429
-> DiagnosticBuilder<'tcx>
428430
{
431+
// (*) This parameter is temporary and used only for phasing
432+
// in the bug fix to #18937. If it is `Some`, it has a kind of
433+
// weird effect -- the diagnostic is reported as a lint, and
434+
// the builder which is returned is marked as canceled.
435+
429436
let mut err =
430437
struct_span_err!(self.tcx.sess,
431438
error_span,
@@ -441,6 +448,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
441448
error_span,
442449
&format!("impl has extra requirement {}", requirement));
443450

451+
if let Some(node_id) = lint_id {
452+
let diagnostic = (*err).clone();
453+
self.tcx.sess.add_lint(EXTRA_REQUIREMENT_IN_IMPL, node_id, error_span, diagnostic);
454+
err.cancel();
455+
}
456+
444457
err
445458
}
446459

@@ -452,14 +465,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
452465
let mut err = match *error {
453466
SelectionError::Unimplemented => {
454467
if let ObligationCauseCode::CompareImplMethodObligation {
455-
item_name, impl_item_def_id, trait_item_def_id
468+
item_name, impl_item_def_id, trait_item_def_id, lint_id
456469
} = obligation.cause.code {
457470
self.report_extra_impl_obligation(
458471
span,
459472
item_name,
460473
impl_item_def_id,
461474
trait_item_def_id,
462-
&format!("`{}`", obligation.predicate))
475+
&format!("`{}`", obligation.predicate),
476+
lint_id)
463477
.emit();
464478
return;
465479
} else {

src/librustc/traits/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,12 @@ pub enum ObligationCauseCode<'tcx> {
138138

139139
ImplDerivedObligation(DerivedObligationCause<'tcx>),
140140

141+
// error derived when matching traits/impls; see ObligationCause for more details
141142
CompareImplMethodObligation {
142143
item_name: ast::Name,
143144
impl_item_def_id: DefId,
144-
trait_item_def_id: DefId
145+
trait_item_def_id: DefId,
146+
lint_id: Option<ast::NodeId>,
145147
},
146148
}
147149

src/librustc/traits/structural_impls.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
197197
}
198198
super::CompareImplMethodObligation { item_name,
199199
impl_item_def_id,
200-
trait_item_def_id } => {
200+
trait_item_def_id,
201+
lint_id } => {
201202
Some(super::CompareImplMethodObligation {
202203
item_name: item_name,
203204
impl_item_def_id: impl_item_def_id,
204205
trait_item_def_id: trait_item_def_id,
206+
lint_id: lint_id,
205207
})
206208
}
207209
}

src/librustc_errors/diagnostic.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::fmt;
66
use syntax_pos::{MultiSpan, Span};
77

88
#[must_use]
9-
#[derive(Clone)]
9+
#[derive(Clone, Debug)]
1010
pub struct Diagnostic {
1111
pub level: Level,
1212
pub message: String,
@@ -16,7 +16,7 @@ pub struct Diagnostic {
1616
}
1717

1818
/// For example a note attached to an error.
19-
#[derive(Clone)]
19+
#[derive(Clone, Debug)]
2020
pub struct SubDiagnostic {
2121
pub level: Level,
2222
pub message: String,
@@ -190,9 +190,3 @@ impl Diagnostic {
190190
self.children.push(sub);
191191
}
192192
}
193-
194-
impl fmt::Debug for Diagnostic {
195-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196-
self.message.fmt(f)
197-
}
198-
}

0 commit comments

Comments
 (0)