mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #92397 - matthiaskrgr:rollup-xnfou17, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #92075 (rustdoc: Only special case struct fields for intra-doc links, not enum variants) - #92118 (Parse and suggest moving where clauses after equals for type aliases) - #92237 (Visit expressions in-order when resolving pattern bindings) - #92340 (rustdoc: Start cleaning up search index generation) - #92351 (Add long error explanation for E0227) - #92371 (Remove pretty printer space inside block with only outer attrs) - #92372 (Print space after formal generic params in fn type) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2b67c30bfe
@ -387,23 +387,23 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||||||
self.print_string(sym.as_str(), style);
|
self.print_string(sym.as_str(), style);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) {
|
fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
|
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) {
|
fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
|
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) {
|
fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||||
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
|
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) {
|
fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
|
self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) {
|
fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||||
self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
|
self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,20 +413,21 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||||||
kind: ast::AttrStyle,
|
kind: ast::AttrStyle,
|
||||||
is_inline: bool,
|
is_inline: bool,
|
||||||
trailing_hardbreak: bool,
|
trailing_hardbreak: bool,
|
||||||
) {
|
) -> bool {
|
||||||
let mut count = 0;
|
let mut printed = false;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.style == kind {
|
if attr.style == kind {
|
||||||
self.print_attribute_inline(attr, is_inline);
|
self.print_attribute_inline(attr, is_inline);
|
||||||
if is_inline {
|
if is_inline {
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
}
|
}
|
||||||
count += 1;
|
printed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if count > 0 && trailing_hardbreak && !is_inline {
|
if printed && trailing_hardbreak && !is_inline {
|
||||||
self.hardbreak_if_not_bol();
|
self.hardbreak_if_not_bol();
|
||||||
}
|
}
|
||||||
|
printed
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_attribute(&mut self, attr: &ast::Attribute) {
|
fn print_attribute(&mut self, attr: &ast::Attribute) {
|
||||||
@ -1646,7 +1647,7 @@ impl<'a> State<'a> {
|
|||||||
self.ann.pre(self, AnnNode::Block(blk));
|
self.ann.pre(self, AnnNode::Block(blk));
|
||||||
self.bopen();
|
self.bopen();
|
||||||
|
|
||||||
self.print_inner_attributes(attrs);
|
let has_attrs = self.print_inner_attributes(attrs);
|
||||||
|
|
||||||
for (i, st) in blk.stmts.iter().enumerate() {
|
for (i, st) in blk.stmts.iter().enumerate() {
|
||||||
match st.kind {
|
match st.kind {
|
||||||
@ -1660,7 +1661,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let empty = attrs.is_empty() && blk.stmts.is_empty();
|
let empty = !has_attrs && blk.stmts.is_empty();
|
||||||
self.bclose_maybe_open(blk.span, empty, close_box);
|
self.bclose_maybe_open(blk.span, empty, close_box);
|
||||||
self.ann.post(self, AnnNode::Block(blk))
|
self.ann.post(self, AnnNode::Block(blk))
|
||||||
}
|
}
|
||||||
@ -2780,34 +2781,34 @@ impl<'a> State<'a> {
|
|||||||
self.word_space(",");
|
self.word_space(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
match *predicate {
|
self.print_where_predicate(predicate);
|
||||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
}
|
||||||
ref bound_generic_params,
|
}
|
||||||
ref bounded_ty,
|
|
||||||
ref bounds,
|
pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
|
||||||
..
|
match predicate {
|
||||||
}) => {
|
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||||
self.print_formal_generic_params(bound_generic_params);
|
bound_generic_params,
|
||||||
self.print_type(bounded_ty);
|
bounded_ty,
|
||||||
self.print_type_bounds(":", bounds);
|
bounds,
|
||||||
}
|
..
|
||||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
}) => {
|
||||||
ref lifetime,
|
self.print_formal_generic_params(bound_generic_params);
|
||||||
ref bounds,
|
self.print_type(bounded_ty);
|
||||||
..
|
self.print_type_bounds(":", bounds);
|
||||||
}) => {
|
}
|
||||||
self.print_lifetime_bounds(*lifetime, bounds);
|
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||||
}
|
lifetime,
|
||||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
bounds,
|
||||||
ref lhs_ty,
|
..
|
||||||
ref rhs_ty,
|
}) => {
|
||||||
..
|
self.print_lifetime_bounds(*lifetime, bounds);
|
||||||
}) => {
|
}
|
||||||
self.print_type(lhs_ty);
|
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
|
||||||
self.space();
|
self.print_type(lhs_ty);
|
||||||
self.word_space("=");
|
self.space();
|
||||||
self.print_type(rhs_ty);
|
self.word_space("=");
|
||||||
}
|
self.print_type(rhs_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2908,10 +2909,7 @@ impl<'a> State<'a> {
|
|||||||
generic_params: &[ast::GenericParam],
|
generic_params: &[ast::GenericParam],
|
||||||
) {
|
) {
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
if !generic_params.is_empty() {
|
self.print_formal_generic_params(generic_params);
|
||||||
self.word("for");
|
|
||||||
self.print_generic_params(generic_params);
|
|
||||||
}
|
|
||||||
let generics = ast::Generics {
|
let generics = ast::Generics {
|
||||||
params: Vec::new(),
|
params: Vec::new(),
|
||||||
where_clause: ast::WhereClause {
|
where_clause: ast::WhereClause {
|
||||||
|
@ -120,6 +120,7 @@ E0223: include_str!("./error_codes/E0223.md"),
|
|||||||
E0224: include_str!("./error_codes/E0224.md"),
|
E0224: include_str!("./error_codes/E0224.md"),
|
||||||
E0225: include_str!("./error_codes/E0225.md"),
|
E0225: include_str!("./error_codes/E0225.md"),
|
||||||
E0226: include_str!("./error_codes/E0226.md"),
|
E0226: include_str!("./error_codes/E0226.md"),
|
||||||
|
E0227: include_str!("./error_codes/E0227.md"),
|
||||||
E0228: include_str!("./error_codes/E0228.md"),
|
E0228: include_str!("./error_codes/E0228.md"),
|
||||||
E0229: include_str!("./error_codes/E0229.md"),
|
E0229: include_str!("./error_codes/E0229.md"),
|
||||||
E0230: include_str!("./error_codes/E0230.md"),
|
E0230: include_str!("./error_codes/E0230.md"),
|
||||||
@ -530,7 +531,6 @@ E0786: include_str!("./error_codes/E0786.md"),
|
|||||||
// E0217, // ambiguous associated type, defined in multiple supertraits
|
// E0217, // ambiguous associated type, defined in multiple supertraits
|
||||||
// E0218, // no associated type defined
|
// E0218, // no associated type defined
|
||||||
// E0219, // associated type defined in higher-ranked supertrait
|
// E0219, // associated type defined in higher-ranked supertrait
|
||||||
E0227, // ambiguous lifetime bound, explicit lifetime bound required
|
|
||||||
// E0233,
|
// E0233,
|
||||||
// E0234,
|
// E0234,
|
||||||
// E0235, // structure constructor specifies a structure of type but
|
// E0235, // structure constructor specifies a structure of type but
|
||||||
|
33
compiler/rustc_error_codes/src/error_codes/E0227.md
Normal file
33
compiler/rustc_error_codes/src/error_codes/E0227.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
This error indicates that the compiler is unable to determine whether there is
|
||||||
|
exactly one unique region in the set of derived region bounds.
|
||||||
|
|
||||||
|
Example of erroneous code:
|
||||||
|
|
||||||
|
```compile_fail,E0227
|
||||||
|
trait Foo<'foo>: 'foo {}
|
||||||
|
trait Bar<'bar>: 'bar {}
|
||||||
|
|
||||||
|
trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {}
|
||||||
|
|
||||||
|
struct Baz<'foo, 'bar> {
|
||||||
|
baz: dyn FooBar<'foo, 'bar>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `baz` can have either `'foo` or `'bar` lifetimes.
|
||||||
|
|
||||||
|
To resolve this error, provide an explicit lifetime:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait Foo<'foo>: 'foo {}
|
||||||
|
trait Bar<'bar>: 'bar {}
|
||||||
|
|
||||||
|
trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {}
|
||||||
|
|
||||||
|
struct Baz<'foo, 'bar, 'baz>
|
||||||
|
where
|
||||||
|
'baz: 'foo + 'bar,
|
||||||
|
{
|
||||||
|
obj: dyn FooBar<'foo, 'bar> + 'baz,
|
||||||
|
}
|
||||||
|
```
|
@ -2327,10 +2327,7 @@ impl<'a> State<'a> {
|
|||||||
arg_names: &[Ident],
|
arg_names: &[Ident],
|
||||||
) {
|
) {
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
if !generic_params.is_empty() {
|
self.print_formal_generic_params(generic_params);
|
||||||
self.word("for");
|
|
||||||
self.print_generic_params(generic_params);
|
|
||||||
}
|
|
||||||
let generics = hir::Generics {
|
let generics = hir::Generics {
|
||||||
params: &[],
|
params: &[],
|
||||||
where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP },
|
where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP },
|
||||||
|
@ -794,6 +794,44 @@ impl<'a> Parser<'a> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits an error that the where clause at the end of a type alias is not
|
||||||
|
/// allowed and suggests moving it.
|
||||||
|
fn error_ty_alias_where(
|
||||||
|
&self,
|
||||||
|
before_where_clause_present: bool,
|
||||||
|
before_where_clause_span: Span,
|
||||||
|
after_predicates: &[WherePredicate],
|
||||||
|
after_where_clause_span: Span,
|
||||||
|
) {
|
||||||
|
let mut err =
|
||||||
|
self.struct_span_err(after_where_clause_span, "where clause not allowed here");
|
||||||
|
if !after_predicates.is_empty() {
|
||||||
|
let mut state = crate::pprust::State::new();
|
||||||
|
if !before_where_clause_present {
|
||||||
|
state.space();
|
||||||
|
state.word_space("where");
|
||||||
|
} else {
|
||||||
|
state.word_space(",");
|
||||||
|
}
|
||||||
|
let mut first = true;
|
||||||
|
for p in after_predicates.iter() {
|
||||||
|
if !first {
|
||||||
|
state.word_space(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
state.print_where_predicate(p);
|
||||||
|
}
|
||||||
|
let suggestion = state.s.eof();
|
||||||
|
err.span_suggestion(
|
||||||
|
before_where_clause_span.shrink_to_hi(),
|
||||||
|
"move it here",
|
||||||
|
suggestion,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
err.emit()
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a `type` alias with the following grammar:
|
/// Parses a `type` alias with the following grammar:
|
||||||
/// ```
|
/// ```
|
||||||
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
|
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
|
||||||
@ -806,9 +844,24 @@ impl<'a> Parser<'a> {
|
|||||||
// Parse optional colon and param bounds.
|
// Parse optional colon and param bounds.
|
||||||
let bounds =
|
let bounds =
|
||||||
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
|
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
|
||||||
|
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
|
|
||||||
let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
|
let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
|
||||||
|
|
||||||
|
if self.token.is_keyword(kw::Where) {
|
||||||
|
let after_where_clause = self.parse_where_clause()?;
|
||||||
|
|
||||||
|
self.error_ty_alias_where(
|
||||||
|
generics.where_clause.has_where_token,
|
||||||
|
generics.where_clause.span,
|
||||||
|
&after_where_clause.predicates,
|
||||||
|
after_where_clause.span,
|
||||||
|
);
|
||||||
|
|
||||||
|
generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
|
|
||||||
Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
|
Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
|
||||||
|
@ -1603,10 +1603,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
pat_src: PatternSource,
|
pat_src: PatternSource,
|
||||||
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
|
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
|
||||||
) {
|
) {
|
||||||
|
// We walk the pattern before declaring the pattern's inner bindings,
|
||||||
|
// so that we avoid resolving a literal expression to a binding defined
|
||||||
|
// by the pattern.
|
||||||
|
visit::walk_pat(self, pat);
|
||||||
self.resolve_pattern_inner(pat, pat_src, bindings);
|
self.resolve_pattern_inner(pat, pat_src, bindings);
|
||||||
// This has to happen *after* we determine which pat_idents are variants:
|
// This has to happen *after* we determine which pat_idents are variants:
|
||||||
self.check_consistent_bindings_top(pat);
|
self.check_consistent_bindings_top(pat);
|
||||||
visit::walk_pat(self, pat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
|
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
|
||||||
|
@ -39,7 +39,6 @@ use crate::clean::Clean;
|
|||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::html::render::cache::ExternalLocation;
|
|
||||||
use crate::html::render::Context;
|
use crate::html::render::Context;
|
||||||
use crate::passes::collect_intra_doc_links::UrlFragment;
|
use crate::passes::collect_intra_doc_links::UrlFragment;
|
||||||
|
|
||||||
@ -339,6 +338,16 @@ impl ExternalCrate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates where an external crate can be found.
|
||||||
|
crate enum ExternalLocation {
|
||||||
|
/// Remote URL root of the external crate
|
||||||
|
Remote(String),
|
||||||
|
/// This external crate can be found in the local doc/ folder
|
||||||
|
Local,
|
||||||
|
/// The external crate could not be found.
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
/// Anything with a source location and set of attributes and, optionally, a
|
/// Anything with a source location and set of attributes and, optionally, a
|
||||||
/// name. That is, anything that can be documented. This doesn't correspond
|
/// name. That is, anything that can be documented. This doesn't correspond
|
||||||
/// directly to the AST's concept of an item; it's a strict superset.
|
/// directly to the AST's concept of an item; it's a strict superset.
|
||||||
|
@ -6,13 +6,13 @@ use rustc_middle::middle::privacy::AccessLevels;
|
|||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use crate::clean::{self, ExternalCrate, ItemId, PrimitiveType};
|
use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::formats::Impl;
|
use crate::formats::Impl;
|
||||||
use crate::html::markdown::short_markdown_summary;
|
use crate::html::markdown::short_markdown_summary;
|
||||||
use crate::html::render::cache::{get_index_search_type, ExternalLocation};
|
use crate::html::render::search_index::get_function_type_for_search;
|
||||||
use crate::html::render::IndexItem;
|
use crate::html::render::IndexItem;
|
||||||
|
|
||||||
/// This cache is used to store information about the [`clean::Crate`] being
|
/// This cache is used to store information about the [`clean::Crate`] being
|
||||||
@ -303,7 +303,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||||||
desc,
|
desc,
|
||||||
parent,
|
parent,
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
search_type: get_index_search_type(&item, self.tcx, self.cache),
|
search_type: get_function_type_for_search(&item, self.tcx),
|
||||||
aliases: item.attrs.get_doc_aliases(),
|
aliases: item.attrs.get_doc_aliases(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,12 @@ use rustc_middle::ty::TyCtxt;
|
|||||||
use rustc_span::def_id::CRATE_DEF_INDEX;
|
use rustc_span::def_id::CRATE_DEF_INDEX;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType};
|
use crate::clean::{
|
||||||
|
self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, ItemId,
|
||||||
|
PrimitiveType,
|
||||||
|
};
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::render::cache::ExternalLocation;
|
|
||||||
use crate::html::render::Context;
|
use crate::html::render::Context;
|
||||||
|
|
||||||
use super::url_parts_builder::UrlPartsBuilder;
|
use super::url_parts_builder::UrlPartsBuilder;
|
||||||
|
@ -13,8 +13,8 @@ use rustc_span::edition::Edition;
|
|||||||
use rustc_span::source_map::FileName;
|
use rustc_span::source_map::FileName;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use super::cache::{build_index, ExternalLocation};
|
|
||||||
use super::print_item::{full_path, item_path, print_item};
|
use super::print_item::{full_path, item_path, print_item};
|
||||||
|
use super::search_index::build_index;
|
||||||
use super::templates;
|
use super::templates;
|
||||||
use super::write_shared::write_shared;
|
use super::write_shared::write_shared;
|
||||||
use super::{
|
use super::{
|
||||||
@ -22,7 +22,7 @@ use super::{
|
|||||||
BASIC_KEYWORDS,
|
BASIC_KEYWORDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::clean::{self, ExternalCrate};
|
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
|
||||||
use crate::config::RenderOptions;
|
use crate::config::RenderOptions;
|
||||||
use crate::docfs::{DocFS, PathError};
|
use crate::docfs::{DocFS, PathError};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
//! These threads are not parallelized (they haven't been a bottleneck yet), and
|
//! These threads are not parallelized (they haven't been a bottleneck yet), and
|
||||||
//! both occur before the crate is rendered.
|
//! both occur before the crate is rendered.
|
||||||
|
|
||||||
crate mod cache;
|
crate mod search_index;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -7,22 +7,12 @@ use rustc_span::symbol::Symbol;
|
|||||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||||
|
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::clean::types::{FnDecl, FnRetTy, GenericBound, Generics, Type, WherePredicate};
|
use crate::clean::types::{FnRetTy, Function, GenericBound, Generics, Type, WherePredicate};
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::html::markdown::short_markdown_summary;
|
use crate::html::markdown::short_markdown_summary;
|
||||||
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
||||||
|
|
||||||
/// Indicates where an external crate can be found.
|
|
||||||
crate enum ExternalLocation {
|
|
||||||
/// Remote URL root of the external crate
|
|
||||||
Remote(String),
|
|
||||||
/// This external crate can be found in the local doc/ folder
|
|
||||||
Local,
|
|
||||||
/// The external crate could not be found.
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Builds the search index from the collected metadata
|
/// Builds the search index from the collected metadata
|
||||||
crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String {
|
crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String {
|
||||||
let mut defid_to_pathid = FxHashMap::default();
|
let mut defid_to_pathid = FxHashMap::default();
|
||||||
@ -42,7 +32,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
|||||||
desc,
|
desc,
|
||||||
parent: Some(did),
|
parent: Some(did),
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
search_type: get_index_search_type(item, tcx, cache),
|
search_type: get_function_type_for_search(item, tcx),
|
||||||
aliases: item.attrs.get_doc_aliases(),
|
aliases: item.attrs.get_doc_aliases(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -191,15 +181,14 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_index_search_type<'tcx>(
|
crate fn get_function_type_for_search<'tcx>(
|
||||||
item: &clean::Item,
|
item: &clean::Item,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
cache: &Cache,
|
|
||||||
) -> Option<IndexItemFunctionType> {
|
) -> Option<IndexItemFunctionType> {
|
||||||
let (mut inputs, mut output) = match *item.kind {
|
let (mut inputs, mut output) = match *item.kind {
|
||||||
clean::FunctionItem(ref f) => get_all_types(&f.generics, &f.decl, tcx, cache),
|
clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx),
|
||||||
clean::MethodItem(ref m, _) => get_all_types(&m.generics, &m.decl, tcx, cache),
|
clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx),
|
||||||
clean::TyMethodItem(ref m) => get_all_types(&m.generics, &m.decl, tcx, cache),
|
clean::TyMethodItem(ref m) => get_fn_inputs_and_outputs(m, tcx),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,12 +200,12 @@ crate fn get_index_search_type<'tcx>(
|
|||||||
|
|
||||||
fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> RenderType {
|
fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> RenderType {
|
||||||
RenderType {
|
RenderType {
|
||||||
name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()),
|
name: get_index_type_name(clean_type).map(|s| s.as_str().to_ascii_lowercase()),
|
||||||
generics: if generics.is_empty() { None } else { Some(generics) },
|
generics: if generics.is_empty() { None } else { Some(generics) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> {
|
fn get_index_type_name(clean_type: &clean::Type) -> Option<Symbol> {
|
||||||
match *clean_type {
|
match *clean_type {
|
||||||
clean::Type::Path { ref path, .. } => {
|
clean::Type::Path { ref path, .. } => {
|
||||||
let path_segment = path.segments.last().unwrap();
|
let path_segment = path.segments.last().unwrap();
|
||||||
@ -226,11 +215,10 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
|
|||||||
let path = &bounds[0].trait_;
|
let path = &bounds[0].trait_;
|
||||||
Some(path.segments.last().unwrap().name)
|
Some(path.segments.last().unwrap().name)
|
||||||
}
|
}
|
||||||
clean::Generic(s) if accept_generic => Some(s),
|
clean::Generic(s) => Some(s),
|
||||||
clean::Primitive(ref p) => Some(p.as_sym()),
|
clean::Primitive(ref p) => Some(p.as_sym()),
|
||||||
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),
|
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_),
|
||||||
clean::Generic(_)
|
clean::BareFunction(_)
|
||||||
| clean::BareFunction(_)
|
|
||||||
| clean::Tuple(_)
|
| clean::Tuple(_)
|
||||||
| clean::Slice(_)
|
| clean::Slice(_)
|
||||||
| clean::Array(_, _)
|
| clean::Array(_, _)
|
||||||
@ -248,20 +236,19 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
|
|||||||
///
|
///
|
||||||
/// Important note: It goes through generics recursively. So if you have
|
/// Important note: It goes through generics recursively. So if you have
|
||||||
/// `T: Option<Result<(), ()>>`, it'll go into `Option` and then into `Result`.
|
/// `T: Option<Result<(), ()>>`, it'll go into `Option` and then into `Result`.
|
||||||
crate fn get_real_types<'tcx>(
|
#[instrument(level = "trace", skip(tcx, res))]
|
||||||
|
fn add_generics_and_bounds_as_types<'tcx>(
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
arg: &Type,
|
arg: &Type,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
recurse: usize,
|
recurse: usize,
|
||||||
res: &mut Vec<TypeWithKind>,
|
res: &mut Vec<TypeWithKind>,
|
||||||
cache: &Cache,
|
|
||||||
) {
|
) {
|
||||||
fn insert_ty(
|
fn insert_ty(
|
||||||
res: &mut Vec<TypeWithKind>,
|
res: &mut Vec<TypeWithKind>,
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
mut generics: Vec<TypeWithKind>,
|
mut generics: Vec<TypeWithKind>,
|
||||||
_cache: &Cache,
|
|
||||||
) {
|
) {
|
||||||
let is_full_generic = ty.is_full_generic();
|
let is_full_generic = ty.is_full_generic();
|
||||||
|
|
||||||
@ -330,6 +317,7 @@ crate fn get_real_types<'tcx>(
|
|||||||
|
|
||||||
if recurse >= 10 {
|
if recurse >= 10 {
|
||||||
// FIXME: remove this whole recurse thing when the recursion bug is fixed
|
// FIXME: remove this whole recurse thing when the recursion bug is fixed
|
||||||
|
// See #59502 for the original issue.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,13 +338,12 @@ crate fn get_real_types<'tcx>(
|
|||||||
for param_def in poly_trait.generic_params.iter() {
|
for param_def in poly_trait.generic_params.iter() {
|
||||||
match ¶m_def.kind {
|
match ¶m_def.kind {
|
||||||
clean::GenericParamDefKind::Type { default: Some(ty), .. } => {
|
clean::GenericParamDefKind::Type { default: Some(ty), .. } => {
|
||||||
get_real_types(
|
add_generics_and_bounds_as_types(
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
tcx,
|
tcx,
|
||||||
recurse + 1,
|
recurse + 1,
|
||||||
&mut ty_generics,
|
&mut ty_generics,
|
||||||
cache,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -364,7 +351,7 @@ crate fn get_real_types<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
|
insert_ty(res, tcx, arg.clone(), ty_generics);
|
||||||
}
|
}
|
||||||
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
|
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
|
||||||
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
|
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
|
||||||
@ -372,10 +359,16 @@ crate fn get_real_types<'tcx>(
|
|||||||
for bound in bound.get_bounds().unwrap_or(&[]) {
|
for bound in bound.get_bounds().unwrap_or(&[]) {
|
||||||
if let Some(path) = bound.get_trait_path() {
|
if let Some(path) = bound.get_trait_path() {
|
||||||
let ty = Type::Path { path };
|
let ty = Type::Path { path };
|
||||||
get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache);
|
add_generics_and_bounds_as_types(
|
||||||
|
generics,
|
||||||
|
&ty,
|
||||||
|
tcx,
|
||||||
|
recurse + 1,
|
||||||
|
&mut ty_generics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
|
insert_ty(res, tcx, arg.clone(), ty_generics);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
|
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
|
||||||
@ -386,10 +379,10 @@ crate fn get_real_types<'tcx>(
|
|||||||
let mut ty_generics = Vec::new();
|
let mut ty_generics = Vec::new();
|
||||||
if let Some(arg_generics) = arg.generics() {
|
if let Some(arg_generics) = arg.generics() {
|
||||||
for gen in arg_generics.iter() {
|
for gen in arg_generics.iter() {
|
||||||
get_real_types(generics, gen, tcx, recurse + 1, &mut ty_generics, cache);
|
add_generics_and_bounds_as_types(generics, gen, tcx, recurse + 1, &mut ty_generics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insert_ty(res, tcx, arg.clone(), ty_generics, cache);
|
insert_ty(res, tcx, arg.clone(), ty_generics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,19 +390,20 @@ crate fn get_real_types<'tcx>(
|
|||||||
///
|
///
|
||||||
/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
|
/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
|
||||||
/// `[u32, Display, Option]`.
|
/// `[u32, Display, Option]`.
|
||||||
crate fn get_all_types<'tcx>(
|
fn get_fn_inputs_and_outputs<'tcx>(
|
||||||
generics: &Generics,
|
func: &Function,
|
||||||
decl: &FnDecl,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
cache: &Cache,
|
|
||||||
) -> (Vec<TypeWithKind>, Vec<TypeWithKind>) {
|
) -> (Vec<TypeWithKind>, Vec<TypeWithKind>) {
|
||||||
|
let decl = &func.decl;
|
||||||
|
let generics = &func.generics;
|
||||||
|
|
||||||
let mut all_types = Vec::new();
|
let mut all_types = Vec::new();
|
||||||
for arg in decl.inputs.values.iter() {
|
for arg in decl.inputs.values.iter() {
|
||||||
if arg.type_.is_self_type() {
|
if arg.type_.is_self_type() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
get_real_types(generics, &arg.type_, tcx, 0, &mut args, cache);
|
add_generics_and_bounds_as_types(generics, &arg.type_, tcx, 0, &mut args);
|
||||||
if !args.is_empty() {
|
if !args.is_empty() {
|
||||||
all_types.extend(args);
|
all_types.extend(args);
|
||||||
} else {
|
} else {
|
||||||
@ -423,7 +417,7 @@ crate fn get_all_types<'tcx>(
|
|||||||
let mut ret_types = Vec::new();
|
let mut ret_types = Vec::new();
|
||||||
match decl.output {
|
match decl.output {
|
||||||
FnRetTy::Return(ref return_type) => {
|
FnRetTy::Return(ref return_type) => {
|
||||||
get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache);
|
add_generics_and_bounds_as_types(generics, return_type, tcx, 0, &mut ret_types);
|
||||||
if ret_types.is_empty() {
|
if ret_types.is_empty() {
|
||||||
if let Some(kind) =
|
if let Some(kind) =
|
||||||
return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
|
return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
|
@ -19,12 +19,11 @@ use rustc_session::Session;
|
|||||||
use rustdoc_json_types as types;
|
use rustdoc_json_types as types;
|
||||||
|
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::clean::ExternalCrate;
|
use crate::clean::types::{ExternalCrate, ExternalLocation};
|
||||||
use crate::config::RenderOptions;
|
use crate::config::RenderOptions;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::FormatRenderer;
|
use crate::formats::FormatRenderer;
|
||||||
use crate::html::render::cache::ExternalLocation;
|
|
||||||
use crate::json::conversions::{from_item_id, IntoWithTcx};
|
use crate::json::conversions::{from_item_id, IntoWithTcx};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -684,27 +684,36 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||||||
if ns != Namespace::ValueNS {
|
if ns != Namespace::ValueNS {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
debug!("looking for variants or fields named {} for {:?}", item_name, did);
|
debug!("looking for fields named {} for {:?}", item_name, did);
|
||||||
// FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
|
// FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
|
||||||
// NOTE: it's different from variant_field because it resolves fields and variants,
|
// NOTE: it's different from variant_field because it only resolves struct fields,
|
||||||
// not variant fields (2 path segments, not 3).
|
// not variant fields (2 path segments, not 3).
|
||||||
|
//
|
||||||
|
// We need to handle struct (and union) fields in this code because
|
||||||
|
// syntactically their paths are identical to associated item paths:
|
||||||
|
// `module::Type::field` and `module::Type::Assoc`.
|
||||||
|
//
|
||||||
|
// On the other hand, variant fields can't be mistaken for associated
|
||||||
|
// items because they look like this: `module::Type::Variant::field`.
|
||||||
|
//
|
||||||
|
// Variants themselves don't need to be handled here, even though
|
||||||
|
// they also look like associated items (`module::Type::Variant`),
|
||||||
|
// because they are real Rust syntax (unlike the intra-doc links
|
||||||
|
// field syntax) and are handled by the compiler's resolver.
|
||||||
let def = match tcx.type_of(did).kind() {
|
let def = match tcx.type_of(did).kind() {
|
||||||
ty::Adt(def, _) => def,
|
ty::Adt(def, _) if !def.is_enum() => def,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let field = if def.is_enum() {
|
let field = def
|
||||||
def.all_fields().find(|item| item.ident.name == item_name)
|
.non_enum_variant()
|
||||||
} else {
|
.fields
|
||||||
def.non_enum_variant().fields.iter().find(|item| item.ident.name == item_name)
|
.iter()
|
||||||
}?;
|
.find(|item| item.ident.name == item_name)?;
|
||||||
let kind = if def.is_enum() { DefKind::Variant } else { DefKind::Field };
|
Some((
|
||||||
let fragment = if def.is_enum() {
|
root_res,
|
||||||
// FIXME: how can the field be a variant?
|
UrlFragment::StructField(field.ident.name),
|
||||||
UrlFragment::Variant(field.ident.name)
|
Some((DefKind::Field, field.did)),
|
||||||
} else {
|
))
|
||||||
UrlFragment::StructField(field.ident.name)
|
|
||||||
};
|
|
||||||
Some((root_res, fragment, Some((kind, field.did))))
|
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Trait, did) => tcx
|
Res::Def(DefKind::Trait, did) => tcx
|
||||||
.associated_items(did)
|
.associated_items(did)
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
#![rustc_dummy]
|
#![rustc_dummy]
|
||||||
#[rustc_dummy]
|
#[rustc_dummy]
|
||||||
fn f() { }
|
fn f() {}
|
||||||
|
|
||||||
#[rustc_dummy]
|
#[rustc_dummy]
|
||||||
fn g() { }
|
fn g() {}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
#![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
|
#![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
|
||||||
#[rustc_dummy = 8]
|
#[rustc_dummy = 8]
|
||||||
fn f() { }
|
fn f() {}
|
||||||
|
|
||||||
#[rustc_dummy(1, 2, 3)]
|
#[rustc_dummy(1, 2, 3)]
|
||||||
fn g() { }
|
fn g() {}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,4 @@
|
|||||||
// pp-exact
|
// pp-exact
|
||||||
|
|
||||||
#[rustfmt::r#final(final)]
|
#[rustfmt::r#final(final)]
|
||||||
fn main() { }
|
fn main() {}
|
||||||
|
@ -45,4 +45,4 @@ mac! {
|
|||||||
}]
|
}]
|
||||||
#[rustc_dummy =
|
#[rustc_dummy =
|
||||||
"aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa"]
|
"aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa"]
|
||||||
fn main() { }
|
fn main() {}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// some single-line non-doc comment
|
// some single-line non-doc comment
|
||||||
|
|
||||||
/// some single line outer-docs
|
/// some single line outer-docs
|
||||||
fn a() { }
|
fn a() {}
|
||||||
|
|
||||||
fn b() {
|
fn b() {
|
||||||
//! some single line inner-docs
|
//! some single line inner-docs
|
||||||
@ -17,7 +17,7 @@ fn b() {
|
|||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
/// some single-line outer-docs preceded by a separator
|
/// some single-line outer-docs preceded by a separator
|
||||||
/// (and trailing whitespaces)
|
/// (and trailing whitespaces)
|
||||||
fn c() { }
|
fn c() {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* some multi-line non-doc comment
|
* some multi-line non-doc comment
|
||||||
@ -26,7 +26,7 @@ fn c() { }
|
|||||||
/**
|
/**
|
||||||
* some multi-line outer-docs
|
* some multi-line outer-docs
|
||||||
*/
|
*/
|
||||||
fn d() { }
|
fn d() {}
|
||||||
|
|
||||||
fn e() {
|
fn e() {
|
||||||
/*!
|
/*!
|
||||||
@ -43,10 +43,10 @@ fn e() {
|
|||||||
/**
|
/**
|
||||||
* some multi-line outer-docs preceded by a separator
|
* some multi-line outer-docs preceded by a separator
|
||||||
*/
|
*/
|
||||||
fn f() { }
|
fn f() {}
|
||||||
|
|
||||||
#[doc = "unsugared outer doc-comments work also"]
|
#[doc = "unsugared outer doc-comments work also"]
|
||||||
fn g() { }
|
fn g() {}
|
||||||
|
|
||||||
fn h() {
|
fn h() {
|
||||||
#![doc = "as do inner ones"]
|
#![doc = "as do inner ones"]
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
// Minimization of issue #59502
|
||||||
|
|
||||||
|
trait MyTrait<T> {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pow<T: MyTrait<T, Output = T>>(arg: T) -> T {
|
||||||
|
arg
|
||||||
|
}
|
12
src/test/ui/error-codes/E0227.rs
Normal file
12
src/test/ui/error-codes/E0227.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
trait Foo<'foo>: 'foo {}
|
||||||
|
trait Bar<'bar>: 'bar {}
|
||||||
|
|
||||||
|
trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {}
|
||||||
|
|
||||||
|
struct Baz<'foo, 'bar> {
|
||||||
|
baz: dyn FooBar<'foo, 'bar>,
|
||||||
|
//~^ ERROR ambiguous lifetime bound, explicit lifetime bound required
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
9
src/test/ui/error-codes/E0227.stderr
Normal file
9
src/test/ui/error-codes/E0227.stderr
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
|
||||||
|
--> $DIR/E0227.rs:7:10
|
||||||
|
|
|
||||||
|
LL | baz: dyn FooBar<'foo, 'bar>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0227`.
|
@ -235,7 +235,7 @@ fn test_expr() {
|
|||||||
#[attr]
|
#[attr]
|
||||||
{}
|
{}
|
||||||
),
|
),
|
||||||
"#[attr] { }", // FIXME
|
"#[attr] {}",
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stringify_expr!(
|
stringify_expr!(
|
||||||
@ -803,7 +803,7 @@ fn test_ty() {
|
|||||||
assert_eq!(stringify_ty!(fn(x: u8)), "fn(x: u8)");
|
assert_eq!(stringify_ty!(fn(x: u8)), "fn(x: u8)");
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
assert_eq!(stringify_ty!(for<> fn()), "fn()");
|
assert_eq!(stringify_ty!(for<> fn()), "fn()");
|
||||||
assert_eq!(stringify_ty!(for<'a> fn()), "for<'a>fn()"); // FIXME
|
assert_eq!(stringify_ty!(for<'a> fn()), "for<'a> fn()");
|
||||||
|
|
||||||
// TyKind::Never
|
// TyKind::Never
|
||||||
assert_eq!(stringify_ty!(!), "!");
|
assert_eq!(stringify_ty!(!), "!");
|
||||||
|
15
src/test/ui/match/expr_before_ident_pat.rs
Normal file
15
src/test/ui/match/expr_before_ident_pat.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#![feature(half_open_range_patterns)]
|
||||||
|
|
||||||
|
macro_rules! funny {
|
||||||
|
($a:expr, $b:ident) => {
|
||||||
|
match [1, 2] {
|
||||||
|
[$a, $b] => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
funny!(a, a);
|
||||||
|
//~^ ERROR cannot find value `a` in this scope
|
||||||
|
//~| ERROR arbitrary expressions aren't allowed in patterns
|
||||||
|
}
|
15
src/test/ui/match/expr_before_ident_pat.stderr
Normal file
15
src/test/ui/match/expr_before_ident_pat.stderr
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error: arbitrary expressions aren't allowed in patterns
|
||||||
|
--> $DIR/expr_before_ident_pat.rs:12:12
|
||||||
|
|
|
||||||
|
LL | funny!(a, a);
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `a` in this scope
|
||||||
|
--> $DIR/expr_before_ident_pat.rs:12:12
|
||||||
|
|
|
||||||
|
LL | funny!(a, a);
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0425`.
|
7
src/test/ui/match/issue-92100.rs
Normal file
7
src/test/ui/match/issue-92100.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#![feature(half_open_range_patterns)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match [1, 2] {
|
||||||
|
[a.., a] => {} //~ ERROR cannot find value `a` in this scope
|
||||||
|
}
|
||||||
|
}
|
9
src/test/ui/match/issue-92100.stderr
Normal file
9
src/test/ui/match/issue-92100.stderr
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
error[E0425]: cannot find value `a` in this scope
|
||||||
|
--> $DIR/issue-92100.rs:5:10
|
||||||
|
|
|
||||||
|
LL | [a.., a] => {}
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0425`.
|
37
src/test/ui/parser/type-alias-where.rs
Normal file
37
src/test/ui/parser/type-alias-where.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// check-fail
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
// Fine, but lints as unused
|
||||||
|
type Foo where u32: Copy = ();
|
||||||
|
// Not fine.
|
||||||
|
type Bar = () where u32: Copy;
|
||||||
|
//~^ ERROR where clause not allowed here
|
||||||
|
type Baz = () where;
|
||||||
|
//~^ ERROR where clause not allowed here
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
// Fine.
|
||||||
|
type Assoc where u32: Copy;
|
||||||
|
// Fine.
|
||||||
|
type Assoc2 where u32: Copy, i32: Copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for u32 {
|
||||||
|
// Fine.
|
||||||
|
type Assoc where u32: Copy = ();
|
||||||
|
// Not fine, suggests moving `i32: Copy`
|
||||||
|
type Assoc2 where u32: Copy = () where i32: Copy;
|
||||||
|
//~^ ERROR where clause not allowed here
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for i32 {
|
||||||
|
// Not fine, suggests moving `u32: Copy`
|
||||||
|
type Assoc = () where u32: Copy;
|
||||||
|
//~^ ERROR where clause not allowed here
|
||||||
|
// Not fine, suggests moving both.
|
||||||
|
type Assoc2 = () where u32: Copy, i32: Copy;
|
||||||
|
//~^ ERROR where clause not allowed here
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
40
src/test/ui/parser/type-alias-where.stderr
Normal file
40
src/test/ui/parser/type-alias-where.stderr
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
error: where clause not allowed here
|
||||||
|
--> $DIR/type-alias-where.rs:8:15
|
||||||
|
|
|
||||||
|
LL | type Bar = () where u32: Copy;
|
||||||
|
| - ^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: move it here: `where u32: Copy`
|
||||||
|
|
||||||
|
error: where clause not allowed here
|
||||||
|
--> $DIR/type-alias-where.rs:10:15
|
||||||
|
|
|
||||||
|
LL | type Baz = () where;
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: where clause not allowed here
|
||||||
|
--> $DIR/type-alias-where.rs:24:38
|
||||||
|
|
|
||||||
|
LL | type Assoc2 where u32: Copy = () where i32: Copy;
|
||||||
|
| - ^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: move it here: `, i32: Copy`
|
||||||
|
|
||||||
|
error: where clause not allowed here
|
||||||
|
--> $DIR/type-alias-where.rs:30:21
|
||||||
|
|
|
||||||
|
LL | type Assoc = () where u32: Copy;
|
||||||
|
| - ^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: move it here: `where u32: Copy`
|
||||||
|
|
||||||
|
error: where clause not allowed here
|
||||||
|
--> $DIR/type-alias-where.rs:33:22
|
||||||
|
|
|
||||||
|
LL | type Assoc2 = () where u32: Copy, i32: Copy;
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: move it here: `where u32: Copy, i32: Copy`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
@ -10,8 +10,8 @@ use regex::Regex;
|
|||||||
|
|
||||||
// A few of those error codes can't be tested but all the others can and *should* be tested!
|
// A few of those error codes can't be tested but all the others can and *should* be tested!
|
||||||
const EXEMPTED_FROM_TEST: &[&str] = &[
|
const EXEMPTED_FROM_TEST: &[&str] = &[
|
||||||
"E0227", "E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0465", "E0476", "E0514",
|
"E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0465", "E0476", "E0514", "E0519",
|
||||||
"E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
|
"E0523", "E0554", "E0640", "E0717", "E0729",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Some error codes don't have any tests apparently...
|
// Some error codes don't have any tests apparently...
|
||||||
|
Loading…
Reference in New Issue
Block a user