diff options
| author | bors <bors@rust-lang.org> | 2015-02-24 17:56:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-02-24 17:56:09 +0000 |
| commit | 0bd15657d93c932611f3aee351b6521cdfa77731 (patch) | |
| tree | 9c6b0adbc679be678c38f2ca305fcdc98907f451 /src/libsyntax/parse | |
| parent | c9ace059e707392ceec46619ed032e93e6256dd5 (diff) | |
| parent | 0c6d1f3b3d22f45c53c8be0a799a6cc42bc752d5 (diff) | |
| download | rust-0bd15657d93c932611f3aee351b6521cdfa77731.tar.gz rust-0bd15657d93c932611f3aee351b6521cdfa77731.zip | |
Auto merge of #22172 - eddyb:almost-there, r=nikomatsakis
Adds `<module::Type>::method` support and makes `module::Type::method` a shorthand for it.
This is most of #16293, except that chaining multiple associated types is not yet supported.
It also fixes #22563 as `impl`s are no longer treated as modules in resolve.
Unfortunately, this is still a *[breaking-change]*:
* If you used a global path to a primitive type, i.e. `::bool`, `::i32` etc. - that was a bug I had to fix.
Solution: remove the leading `::`.
* If you passed explicit `impl`-side type parameters to an inherent method, e.g.:
```rust
struct Foo<T>(T);
impl<A, B> Foo<(A, B)> {
fn pair(a: A, b: B) -> Foo<(A, B)> { Foo((a, b)) }
}
Foo::<A, B>::pair(a, b)
// Now that is sugar for:
<Foo<A, B>>::pair(a, b)
// Which isn't valid because `Foo` has only one type parameter.
// Solution: replace with:
Foo::<(A, B)>::pair(a, b)
// And, if possible, remove the explicit type param entirely:
Foo::pair(a, b)
```
* If you used the `QPath`-related `AstBuilder` methods @hugwijst added in #21943.
The methods still exist, but `QPath` was replaced by `QSelf`, with the actual path stored separately.
Solution: unpack the pair returned by `cx.qpath` to get the two arguments for `cx.expr_qpath`.
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 95 |
2 files changed, 70 insertions, 39 deletions
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 43dfcbae57e..4d099529cb4 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -774,7 +774,7 @@ mod test { assert!(string_to_expr("a".to_string()) == P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 1), global: false, segments: vec!( @@ -792,7 +792,7 @@ mod test { assert!(string_to_expr("::a::b".to_string()) == P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 6), global: true, segments: vec!( @@ -974,7 +974,7 @@ mod test { id: ast::DUMMY_NODE_ID, node:ast::ExprRet(Some(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node:ast::ExprPath(ast::Path{ + node:ast::ExprPath(None, ast::Path{ span: sp(7, 8), global: false, segments: vec!( @@ -995,7 +995,7 @@ mod test { P(Spanned{ node: ast::StmtExpr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span:sp(0,1), global:false, segments: vec!( @@ -1041,7 +1041,7 @@ mod test { node: ast::ItemFn(P(ast::FnDecl { inputs: vec!(ast::Arg{ ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, - node: ast::TyPath(ast::Path{ + node: ast::TyPath(None, ast::Path{ span:sp(10,13), global:false, segments: vec!( @@ -1051,7 +1051,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, ast::DUMMY_NODE_ID), + }), span:sp(10,13) }), pat: P(ast::Pat { @@ -1084,7 +1084,7 @@ mod test { stmts: vec!(P(Spanned{ node: ast::StmtSemi(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path{ span:sp(17,18), global:false, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fec33eddb91..f171e8279f4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -25,7 +25,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; @@ -43,7 +43,7 @@ use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; -use ast::{QPath, RequiredMethod}; +use ast::{QSelf, RequiredMethod}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub, StrStyle}; @@ -53,7 +53,7 @@ use ast::{TtDelimited, TtSequence, TtToken}; use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; use ast::{TyFixedLengthVec, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; -use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; +use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef,}; use ast::{UnnamedField, UnsafeBlock}; @@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprPath(pt))) + Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt))) } token::Interpolated(token::NtBlock(_)) => { // FIXME: The following avoids an issue with lexical borrowck scopes, @@ -1076,8 +1076,7 @@ impl<'a> Parser<'a> { } pub fn parse_ty_path(&mut self) -> Ty_ { - let path = self.parse_path(LifetimeAndTypesWithoutColons); - TyPath(path, ast::DUMMY_NODE_ID) + TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons)) } /// parse a TyBareFn type: @@ -1525,19 +1524,36 @@ impl<'a> Parser<'a> { } else if self.eat_lt() { // QUALIFIED PATH `<TYPE as TRAIT_REF>::item` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; + self.expect(&token::Gt); self.expect(&token::ModSep); - let item_name = self.parse_ident(); - TyQPath(P(QPath { - self_type: self_type, - trait_ref: P(trait_ref), - item_path: ast::PathSegment { - identifier: item_name, - parameters: ast::PathParameters::none() - } - })) + + path.segments.push(ast::PathSegment { + identifier: self.parse_ident(), + parameters: ast::PathParameters::none() + }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + + TyPath(Some(qself), path) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2178,7 +2194,7 @@ impl<'a> Parser<'a> { }, token::Plain) => { self.bump(); let path = ast_util::ident_to_path(mk_sp(lo, hi), id); - ex = ExprPath(path); + ex = ExprPath(None, path); hi = self.last_span.hi; } token::OpenDelim(token::Bracket) => { @@ -2220,10 +2236,22 @@ impl<'a> Parser<'a> { if self.eat_lt() { // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; self.expect(&token::Gt); self.expect(&token::ModSep); + let item_name = self.parse_ident(); let parameters = if self.eat(&token::ModSep) { self.expect_lt(); @@ -2238,15 +2266,18 @@ impl<'a> Parser<'a> { } else { ast::PathParameters::none() }; + path.segments.push(ast::PathSegment { + identifier: item_name, + parameters: parameters + }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + let hi = self.span.hi; - return self.mk_expr(lo, hi, ExprQPath(P(QPath { - self_type: self_type, - trait_ref: P(trait_ref), - item_path: ast::PathSegment { - identifier: item_name, - parameters: parameters - } - }))); + return self.mk_expr(lo, hi, ExprPath(Some(qself), path)); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); @@ -2386,7 +2417,7 @@ impl<'a> Parser<'a> { } hi = pth.span.hi; - ex = ExprPath(pth); + ex = ExprPath(None, pth); } else { // other literal expression let lit = self.parse_lit(); @@ -3428,7 +3459,7 @@ impl<'a> Parser<'a> { let end = if self.token.is_ident() || self.token.is_path() { let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; - self.mk_expr(lo, hi, ExprPath(path)) + self.mk_expr(lo, hi, ExprPath(None, path)) } else { self.parse_literal_maybe_minus() }; @@ -4815,10 +4846,10 @@ impl<'a> Parser<'a> { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. match ty.node { - TyPath(ref path, node_id) => { + TyPath(None, ref path) => { Some(TraitRef { path: (*path).clone(), - ref_id: node_id, + ref_id: ty.id, }) } _ => { |
