Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
2e15f4b8
Commit
2e15f4b8
authored
Jan 23, 2013
by
Robert Griesemer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
go/types: typechecking conversions, part 1 (non-constants)
R=adonovan CC=golang-dev
https://golang.org/cl/7103058
parent
249af5c8
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
89 additions
and
2 deletions
+89
-2
conversions.go
src/pkg/go/types/conversions.go
+89
-2
No files found.
src/pkg/go/types/conversions.go
View file @
2e15f4b8
...
...
@@ -28,10 +28,18 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota
goto
Error
}
// TODO(gri) fix this - implement all checks and constant evaluation
if
x
.
mode
!=
constant
||
!
isConstType
(
typ
)
{
if
x
.
mode
==
constant
&&
isConstType
(
typ
)
{
// constant conversion
// TODO(gri) implement this
}
else
{
// non-constant conversion
if
!
x
.
isConvertible
(
typ
)
{
check
.
invalidOp
(
conv
.
Pos
(),
"cannot convert %s to %s"
,
x
,
typ
)
goto
Error
}
x
.
mode
=
value
}
x
.
expr
=
conv
x
.
typ
=
typ
return
...
...
@@ -39,3 +47,82 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota
Error
:
x
.
mode
=
invalid
}
func
(
x
*
operand
)
isConvertible
(
T
Type
)
bool
{
// "x is assignable to T"
if
x
.
isAssignable
(
T
)
{
return
true
}
// "x's type and T have identical underlying types"
V
:=
x
.
typ
Vu
:=
underlying
(
V
)
Tu
:=
underlying
(
T
)
if
isIdentical
(
Vu
,
Tu
)
{
return
true
}
// "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
if
V
,
ok
:=
V
.
(
*
Pointer
);
ok
{
if
T
,
ok
:=
T
.
(
*
Pointer
);
ok
{
if
isIdentical
(
underlying
(
V
.
Base
),
underlying
(
T
.
Base
))
{
return
true
}
}
}
// "x's type and T are both integer or floating point types"
if
(
isInteger
(
V
)
||
isFloat
(
V
))
&&
(
isInteger
(
T
)
||
isFloat
(
T
))
{
return
true
}
// "x's type and T are both complex types"
if
isComplex
(
V
)
&&
isComplex
(
T
)
{
return
true
}
// "x is an integer or a slice of bytes or runes and T is a string type"
if
(
isInteger
(
V
)
||
isBytesOrRunes
(
Vu
))
&&
isString
(
T
)
{
return
true
}
// "x is a string and T is a slice of bytes or runes"
if
isString
(
V
)
&&
isBytesOrRunes
(
Tu
)
{
return
true
}
// package unsafe:
// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
if
(
isPointer
(
Vu
)
||
isUintptr
(
Vu
))
&&
isUnsafePointer
(
T
)
{
return
true
}
// "and vice versa"
if
isUnsafePointer
(
V
)
&&
(
isPointer
(
Tu
)
||
isUintptr
(
Tu
))
{
return
true
}
return
false
}
func
isUintptr
(
typ
Type
)
bool
{
t
,
ok
:=
typ
.
(
*
Basic
)
return
ok
&&
t
.
Kind
==
Uintptr
}
func
isUnsafePointer
(
typ
Type
)
bool
{
t
,
ok
:=
typ
.
(
*
Basic
)
return
ok
&&
t
.
Kind
==
UnsafePointer
}
func
isPointer
(
typ
Type
)
bool
{
_
,
ok
:=
typ
.
(
*
Pointer
)
return
ok
}
func
isBytesOrRunes
(
typ
Type
)
bool
{
if
s
,
ok
:=
typ
.
(
*
Slice
);
ok
{
t
,
ok
:=
underlying
(
s
.
Elt
)
.
(
*
Basic
)
return
ok
&&
(
t
.
Kind
==
Byte
||
t
.
Kind
==
Rune
)
}
return
false
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment