Skip to content

Commit d902752

Browse files
committed
Auto merge of rust-lang#77118 - exrook:stability-generic-parameters-2, r=varkor
Stability annotations on generic parameters (take 2.5) Rebase of rust-lang#72314 + more tests Implements rust-lang/wg-allocators#2.
2 parents b836329 + 98eab09 commit d902752

File tree

9 files changed

+1171
-34
lines changed

9 files changed

+1171
-34
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1822,13 +1822,17 @@ impl EncodeContext<'a, 'tcx> {
18221822
EntryKind::TypeParam,
18231823
default.is_some(),
18241824
);
1825+
if default.is_some() {
1826+
self.encode_stability(def_id.to_def_id());
1827+
}
18251828
}
18261829
GenericParamKind::Const { .. } => {
18271830
self.encode_info_for_generic_param(
18281831
def_id.to_def_id(),
18291832
EntryKind::ConstParam,
18301833
true,
18311834
);
1835+
// FIXME(const_generics:defaults)
18321836
}
18331837
}
18341838
}

compiler/rustc_middle/src/middle/stability.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,27 @@ impl<'tcx> TyCtxt<'tcx> {
392392
/// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
393393
/// exist, emits an error.
394394
///
395-
/// Additionally, this function will also check if the item is deprecated. If so, and `id` is
396-
/// not `None`, a deprecated lint attached to `id` will be emitted.
395+
/// This function will also check if the item is deprecated.
396+
/// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
397397
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
398+
self.check_optional_stability(def_id, id, span, |span, def_id| {
399+
// The API could be uncallable for other reasons, for example when a private module
400+
// was referenced.
401+
self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id));
402+
})
403+
}
404+
405+
/// Like `check_stability`, except that we permit items to have custom behaviour for
406+
/// missing stability attributes (not necessarily just emit a `bug!`). This is necessary
407+
/// for default generic parameters, which only have stability attributes if they were
408+
/// added after the type on which they're defined.
409+
pub fn check_optional_stability(
410+
self,
411+
def_id: DefId,
412+
id: Option<HirId>,
413+
span: Span,
414+
unmarked: impl FnOnce(Span, DefId) -> (),
415+
) {
398416
let soft_handler = |lint, span, msg: &_| {
399417
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
400418
lint.build(msg).emit()
@@ -405,11 +423,7 @@ impl<'tcx> TyCtxt<'tcx> {
405423
EvalResult::Deny { feature, reason, issue, is_soft } => {
406424
report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler)
407425
}
408-
EvalResult::Unmarked => {
409-
// The API could be uncallable for other reasons, for example when a private module
410-
// was referenced.
411-
self.sess.delay_span_bug(span, &format!("encountered unmarked API: {:?}", def_id));
412-
}
426+
EvalResult::Unmarked => unmarked(span, def_id),
413427
}
414428
}
415429

compiler/rustc_passes/src/stability.rs

+122-26
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@ enum AnnotationKind {
3737
Container,
3838
}
3939

40+
/// Whether to inherit deprecation flags for nested items. In most cases, we do want to inherit
41+
/// deprecation, because nested items rarely have individual deprecation attributes, and so
42+
/// should be treated as deprecated if their parent is. However, default generic parameters
43+
/// have separate deprecation attributes from their parents, so we do not wish to inherit
44+
/// deprecation in this case. For example, inheriting deprecation for `T` in `Foo<T>`
45+
/// would cause a duplicate warning arising from both `Foo` and `T` being deprecated.
46+
#[derive(Clone)]
47+
enum InheritDeprecation {
48+
Yes,
49+
No,
50+
}
51+
52+
impl InheritDeprecation {
53+
fn yes(&self) -> bool {
54+
matches!(self, InheritDeprecation::Yes)
55+
}
56+
}
57+
4058
// A private tree-walker for producing an Index.
4159
struct Annotator<'a, 'tcx> {
4260
tcx: TyCtxt<'tcx>,
@@ -56,14 +74,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
5674
attrs: &[Attribute],
5775
item_sp: Span,
5876
kind: AnnotationKind,
77+
inherit_deprecation: InheritDeprecation,
5978
visit_children: F,
6079
) where
6180
F: FnOnce(&mut Self),
6281
{
6382
debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
6483
let mut did_error = false;
6584
if !self.tcx.features().staged_api {
66-
did_error = self.forbid_staged_api_attrs(hir_id, attrs);
85+
did_error = self.forbid_staged_api_attrs(hir_id, attrs, inherit_deprecation.clone());
6786
}
6887

6988
let depr =
@@ -80,9 +99,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
8099
let depr_entry = DeprecationEntry::local(depr.clone(), hir_id);
81100
self.index.depr_map.insert(hir_id, depr_entry);
82101
} else if let Some(parent_depr) = self.parent_depr.clone() {
83-
is_deprecated = true;
84-
info!("tagging child {:?} as deprecated from parent", hir_id);
85-
self.index.depr_map.insert(hir_id, parent_depr);
102+
if inherit_deprecation.yes() {
103+
is_deprecated = true;
104+
info!("tagging child {:?} as deprecated from parent", hir_id);
105+
self.index.depr_map.insert(hir_id, parent_depr);
106+
}
86107
}
87108

88109
if self.tcx.features().staged_api {
@@ -186,7 +207,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
186207
if stab.is_none() {
187208
debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
188209
if let Some(stab) = self.parent_stab {
189-
if stab.level.is_unstable() {
210+
if inherit_deprecation.yes() && stab.level.is_unstable() {
190211
self.index.stab_map.insert(hir_id, stab);
191212
}
192213
}
@@ -237,7 +258,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
237258
}
238259

239260
// returns true if an error occurred, used to suppress some spurious errors
240-
fn forbid_staged_api_attrs(&mut self, hir_id: HirId, attrs: &[Attribute]) -> bool {
261+
fn forbid_staged_api_attrs(
262+
&mut self,
263+
hir_id: HirId,
264+
attrs: &[Attribute],
265+
inherit_deprecation: InheritDeprecation,
266+
) -> bool {
241267
// Emit errors for non-staged-api crates.
242268
let unstable_attrs = [
243269
sym::unstable,
@@ -265,7 +291,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
265291
// Propagate unstability. This can happen even for non-staged-api crates in case
266292
// -Zforce-unstable-if-unmarked is set.
267293
if let Some(stab) = self.parent_stab {
268-
if stab.level.is_unstable() {
294+
if inherit_deprecation.yes() && stab.level.is_unstable() {
269295
self.index.stab_map.insert(hir_id, stab);
270296
}
271297
}
@@ -301,54 +327,119 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
301327
}
302328
hir::ItemKind::Struct(ref sd, _) => {
303329
if let Some(ctor_hir_id) = sd.ctor_hir_id() {
304-
self.annotate(ctor_hir_id, &i.attrs, i.span, AnnotationKind::Required, |_| {})
330+
self.annotate(
331+
ctor_hir_id,
332+
&i.attrs,
333+
i.span,
334+
AnnotationKind::Required,
335+
InheritDeprecation::Yes,
336+
|_| {},
337+
)
305338
}
306339
}
307340
_ => {}
308341
}
309342

310-
self.annotate(i.hir_id, &i.attrs, i.span, kind, |v| intravisit::walk_item(v, i));
343+
self.annotate(i.hir_id, &i.attrs, i.span, kind, InheritDeprecation::Yes, |v| {
344+
intravisit::walk_item(v, i)
345+
});
311346
self.in_trait_impl = orig_in_trait_impl;
312347
}
313348

314349
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
315-
self.annotate(ti.hir_id, &ti.attrs, ti.span, AnnotationKind::Required, |v| {
316-
intravisit::walk_trait_item(v, ti);
317-
});
350+
self.annotate(
351+
ti.hir_id,
352+
&ti.attrs,
353+
ti.span,
354+
AnnotationKind::Required,
355+
InheritDeprecation::Yes,
356+
|v| {
357+
intravisit::walk_trait_item(v, ti);
358+
},
359+
);
318360
}
319361

320362
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
321363
let kind =
322364
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
323-
self.annotate(ii.hir_id, &ii.attrs, ii.span, kind, |v| {
365+
self.annotate(ii.hir_id, &ii.attrs, ii.span, kind, InheritDeprecation::Yes, |v| {
324366
intravisit::walk_impl_item(v, ii);
325367
});
326368
}
327369

328370
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
329-
self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required, |v| {
330-
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
331-
v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required, |_| {});
332-
}
371+
self.annotate(
372+
var.id,
373+
&var.attrs,
374+
var.span,
375+
AnnotationKind::Required,
376+
InheritDeprecation::Yes,
377+
|v| {
378+
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
379+
v.annotate(
380+
ctor_hir_id,
381+
&var.attrs,
382+
var.span,
383+
AnnotationKind::Required,
384+
InheritDeprecation::Yes,
385+
|_| {},
386+
);
387+
}
333388

334-
intravisit::walk_variant(v, var, g, item_id)
335-
})
389+
intravisit::walk_variant(v, var, g, item_id)
390+
},
391+
)
336392
}
337393

338394
fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) {
339-
self.annotate(s.hir_id, &s.attrs, s.span, AnnotationKind::Required, |v| {
340-
intravisit::walk_struct_field(v, s);
341-
});
395+
self.annotate(
396+
s.hir_id,
397+
&s.attrs,
398+
s.span,
399+
AnnotationKind::Required,
400+
InheritDeprecation::Yes,
401+
|v| {
402+
intravisit::walk_struct_field(v, s);
403+
},
404+
);
342405
}
343406

344407
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
345-
self.annotate(i.hir_id, &i.attrs, i.span, AnnotationKind::Required, |v| {
346-
intravisit::walk_foreign_item(v, i);
347-
});
408+
self.annotate(
409+
i.hir_id,
410+
&i.attrs,
411+
i.span,
412+
AnnotationKind::Required,
413+
InheritDeprecation::Yes,
414+
|v| {
415+
intravisit::walk_foreign_item(v, i);
416+
},
417+
);
348418
}
349419

350420
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
351-
self.annotate(md.hir_id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
421+
self.annotate(
422+
md.hir_id,
423+
&md.attrs,
424+
md.span,
425+
AnnotationKind::Required,
426+
InheritDeprecation::Yes,
427+
|_| {},
428+
);
429+
}
430+
431+
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
432+
let kind = match &p.kind {
433+
// FIXME(const_generics:defaults)
434+
hir::GenericParamKind::Type { default, .. } if default.is_some() => {
435+
AnnotationKind::Container
436+
}
437+
_ => AnnotationKind::Prohibited,
438+
};
439+
440+
self.annotate(p.hir_id, &p.attrs, p.span, kind, InheritDeprecation::No, |v| {
441+
intravisit::walk_generic_param(v, p);
442+
});
352443
}
353444
}
354445

@@ -422,6 +513,10 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
422513
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
423514
self.check_missing_stability(md.hir_id, md.span);
424515
}
516+
517+
// Note that we don't need to `check_missing_stability` for default generic parameters,
518+
// as we assume that any default generic parameters without attributes are automatically
519+
// stable (assuming they have not inherited instability from their parent).
425520
}
426521

427522
fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
@@ -484,6 +579,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
484579
&krate.item.attrs,
485580
krate.item.span,
486581
AnnotationKind::Required,
582+
InheritDeprecation::Yes,
487583
|v| intravisit::walk_crate(v, krate),
488584
);
489585
}

compiler/rustc_typeck/src/astconv/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
360360
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
361361
self.ast_region_to_region(&lt, Some(param)).into()
362362
}
363-
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
363+
(GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
364+
if *has_default {
365+
tcx.check_optional_stability(
366+
param.def_id,
367+
Some(arg.id()),
368+
arg.span(),
369+
|_, _| {
370+
// Default generic parameters may not be marked
371+
// with stability attributes, i.e. when the
372+
// default parameter was defined at the same time
373+
// as the rest of the type. As such, we ignore missing
374+
// stability attributes.
375+
},
376+
)
377+
}
364378
if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
365379
inferred_params.push(ty.span);
366380
tcx.ty_error().into()

0 commit comments

Comments
 (0)